【Android】侧滑菜单

一、普通侧滑

1、新建left_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <LinearLayout 
        android:layout_height="wrap_content"
		android:layout_width="match_parent"
		android:layout_centerInParent="true"
		
		android:orientation="vertical">
		
		<TextView 
		    android:layout_height="wrap_content"
		    android:layout_width="wrap_content"
		    android:text="row 1"
		    android:textSize="30sp"
		    android:layout_gravity="center"
		    />  
		<TextView 
		    android:layout_height="wrap_content"
		    android:layout_width="wrap_content"
		    android:text="row 2"
		    android:textSize="30sp"
			android:layout_gravity="center"
		    />
		<TextView 
		    android:layout_height="wrap_content"
		    android:layout_width="wrap_content"
		    android:text="row 3"
		    android:textSize="30sp"
		    android:layout_gravity="center"
		    />  
		 <TextView 
		    android:layout_height="wrap_content"
		    android:layout_width="wrap_content"
		    android:text="row 4"
		    android:textSize="30sp"
		    android:layout_gravity="center"
		    />    
        
    </LinearLayout>

</RelativeLayout>


2、完成 activity_main 布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.slidingmenu.MainActivity" >

	<com.example.slidingmenu.view.slidingMenu
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
<pre name="code" class="html"><span style="white-space:pre">	</span>    android:background="@drawable/menu"<span style="font-family: Arial, Helvetica, sans-serif;">></span>
<LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal"> <include layout="@layout/left_menu"/> <LinearLayout android:layout_width="match_parent"android:layout_height="match_parent" android:background="@drawable/main1"> </LinearLayout> </LinearLayout> </com.example.slidingmenu.view.slidingMenu> </RelativeLayout>

 
 

3.自定义HorizontalScrollView

自定义ViewGroup

(1)onMeasure(起到测量的作用)

决定内部view(子view)的宽和高,以及自己的宽和高

(2)onLayout

决定子view放置的位置

(3)onTouchEvent(在这里,要判断用户手指操作状态)

public class slidingMenu extends HorizontalScrollView {

	private LinearLayout mWapper;
	private ViewGroup mMenu;
	private ViewGroup mContent;
	private int screenWidth;//屏幕宽度
	private int mMenuWidth;//menu宽度
	private int menuRightPadding ;//menu与屏幕右侧边距
	private boolean once = false;//防止onMeasure()多次调用
	
	/**
	 * 未使用自定义属性时调用
	 * @param context
	 * @param attrs
	 */
	public slidingMenu(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.setVerticalScrollBarEnabled(false);//去掉滚动条
		//获取宽度
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		screenWidth = outMetrics.widthPixels;
		//把dp转化为px,默认60dp
		menuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics());
	}
	/**
	 * 设置子view的宽和高,自己的宽和高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		if(!once){
			mWapper = (LinearLayout) getChildAt(0);//layout里第一个元素
			mMenu = (ViewGroup) mWapper.getChildAt(0);//LinearLayout里第一个元素
			mContent = (ViewGroup) mWapper.getChildAt(1);//LinearLayout里第一个元素
			//menu的宽度
			mMenuWidth = mMenu.getLayoutParams().width = screenWidth - menuRightPadding;
			mContent.getLayoutParams().width = screenWidth;
			
			once = true;
		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	/**
	 * 通过设置偏移量将menu隐藏
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if(changed){
			this.scrollTo(mMenuWidth,0);//将menu隐藏到左侧
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch(action){
		case MotionEvent.ACTION_UP://用户手指抬起时
			int scrollX = getScrollX();//左侧超出屏幕的隐藏部分宽度
		
			if(scrollX >= mMenuWidth/2){
				this.smoothScrollTo(mMenuWidth, 0);
			}else{
				this.smoothScrollTo(0, 0);
			}
			
		return true;
		}
		
		return super.onTouchEvent(ev);
	}
}

4、添加菜单切换按钮

(1)修改代码

public class slidingMenu extends HorizontalScrollView {

	private LinearLayout mWapper;
	private ViewGroup mMenu;
	private ViewGroup mContent;
	private int screenWidth;
	private int mMenuWidth;
	private int menuRightPadding ;
	private boolean once = false;
	private boolean isOpen ;//表示menu是否打开的状态
	
	public slidingMenu(Context context, AttributeSet attrs) {
		super(context, attrs);
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		screenWidth = outMetrics.widthPixels;
		menuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, context.getResources().getDisplayMetrics());
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		if(!once){
			mWapper = (LinearLayout) getChildAt(0);
			mMenu = (ViewGroup) mWapper.getChildAt(0);
			mContent = (ViewGroup) mWapper.getChildAt(1);
			mMenuWidth = mMenu.getLayoutParams().width = screenWidth - menuRightPadding;
			mContent.getLayoutParams().width = screenWidth;
			
			once = true;
		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if(changed){
			this.scrollTo(mMenuWidth,0);
		}
	}
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch(action){
		case MotionEvent.ACTION_UP:
			int scrollX = getScrollX();
		
			if(scrollX >= mMenuWidth/2){
				this.smoothScrollTo(mMenuWidth, 0);
				isOpen = false;//实时改变isOpen状态
			}else{
				this.smoothScrollTo(0, 0);
				isOpen = true;//实时改变isOpen状态
			}
		return true;
		}
		return super.onTouchEvent(ev);
	}
	/**
	 * 打开菜单
	 */
	public void openMenu(){
		if(isOpen) return;
		this.smoothScrollTo(0, 0);
		isOpen = true;
	}
	/**
	 * 关闭菜单
	 */
	public void closeMenu(){
		if(!isOpen) return;
		this.smoothScrollTo(mMenuWidth, 0);
		isOpen = false;
	}
	/**
	 * 切换菜单
	 */
	public void toggle(){
		if(isOpen){
			closeMenu();
		}else{
			openMenu();
		}
	}
	
}
(2) 添加 button

<Button 
	android:onClick="toggleMenu"
	android:layout_width="80dp"
	android:layout_height="50dp"
	android:text="TOG"/>


(3)在MainActivity添加方法

public class MainActivity extends ActionBarActivity {
	private slidingMenu mMenu;//创建mMenu

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        
        mMenu = (slidingMenu) findViewById(R.id.menu);
        
    }

    public void toggleMenu(View view){
    	mMenu.toggle();
    }
    
}

 

二、抽屉侧滑

随着move,我们人为使menu偏移,所以看起来好像没动。。。。

在这里还要使用到nineoldandroids-2.4.0.jar 包实现属性动画效果,可以向下兼容

只需要重写slidingMenuonScrollChanged()方法

<span style="white-space:pre">	</span>/**
	 * 发生滚动时
	 */
	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);
		float scale = l*1.0f/mMenuWidth;//1~0
		//调用属性动画,设置TranslationX
		ViewHelper.setTranslationX(mMenu, mMenuWidth*scale);
		
		
	}

    android:background="@drawable/menu"

二、抽屉侧滑+缩放

<span style="white-space:pre">	</span>/**
	 * 发生滚动时
	 */
	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);
		float scale = l*1.0f/mMenuWidth;//1~0
		
		ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.7f);//*0.7使得menu一部分从屏幕外被拉进来
		//缩放部分,缩放前还要设置缩放中心点

		float rightScale = 0.7f + 0.3f*scale;//用于content缩放
		float leftScale = 1.0f - scale*0.3f;//用于menu缩放
		float leftAlpha = 0.6f + 0.4f*(1-scale);//用于透明度
		
		ViewHelper.setScaleX(mContent,leftScale);
		ViewHelper.setScaleY(mContent,leftScale);
		ViewHelper.setAlpha(mMenu,leftAlpha);
		
		ViewHelper.setPivotX(mContent, 0);
		ViewHelper.setPivotY(mContent, mContent.getHeight()/2);
		ViewHelper.setScaleX(mContent, rightScale);
		ViewHelper.setScaleY(mContent, rightScale);
		
	}





    android:background="@drawable/menu"

你可能感兴趣的:(【Android】侧滑菜单)