滑动菜单特效实现

这次是滑动特效实现,代码是看的郭霖老师的,但是看了代码有点懵懵懂懂的,所以自己就对代码进行更详细的解读。


步骤:

1.首先我们要初始化几个参数:

menuPadding=100; //完全显示Menu时,留给Content的宽度

screenWidth; //初始化为屏幕宽度

leftEdge; //也就是menu滑到最左边,menu布局leftMargin的最小值,也就是后面滑动只要小于了它,就不能再向左滑动了。

rightEdge; //menu滑到最右边,leftMargin不能再增加了。

2. 重写 onTouch事件,分为:手指按下,手指移动,手指抬起。

按下时:获取按下的x值;移动时:判断滑动的位置,根据 leftEdge最左边 ,rightEdge最右边;

抬起时:判断是否需要显示 Menu或者 Content 。

3. 根据AsyncTask来显示手指在屏幕上滑动的样子。(最后我也不清楚为什么用到AsyncTask)


这是我 activity_main 代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    android:orientation="horizontal">

    <LinearLayout 
        android:id="@+id/menu"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="@color/yellow"
        >
        
    </LinearLayout>
    <LinearLayout 
        android:id="@+id/content"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="@color/blue">
        
    </LinearLayout>

</LinearLayout>

我的 MainActivity.java :


package com.slidemenudemo;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class MainActivity extends Activity implements OnTouchListener {

	/**
	 * 自定义的速度,当用户达到这个速度时,
	 * 就可以是menu到content的转换,或者content到menu的转换
	 */
	private static final int SPEED=200;
	/**
	 * 手指按下时X的坐标
	 */
	private float xDown;
	/**
	 * 手指抬起时X的坐标
	 */
	private float xUp;
	/**
	 * 手指滑动时X的坐标
	 */
	private float xMove;
	private View menu;
	private View content;
    /**
     * menu菜单的参数,根据它来改变leftMargin
     */
	private LinearLayout.LayoutParams menuParams;
	private boolean isMenuVisible;
	private int screenWidth;
	/**
	 * menu滑动到最左端时的最小值
	 */
	private int leftEdge;
	/**
	 * menu滑动到最右端时的最大值
	 */
	private int rightEdge;
	/**
	 * menu显示时,留给content的宽度
	 */
	private int menuPadding;
	/**
	 * 用于计算手指滑动的速度。
	 */
	private VelocityTracker mVelocityTracker;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
		content.setOnTouchListener(this);
	}
	/**
	 * 初始化
	 */
	private void initView(){
		WindowManager window=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
		screenWidth=window.getDefaultDisplay().getWidth();
		menu=findViewById(R.id.menu);
		content=findViewById(R.id.content);
		menuParams=(LinearLayout.LayoutParams)menu.getLayoutParams();
		menuPadding=100;
		menuParams.width=screenWidth-menuPadding;
		leftEdge=-menuParams.width;
		rightEdge=0;
		menuParams.leftMargin=leftEdge;
		content.getLayoutParams().width=screenWidth;
	}
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		createVelocityTracker(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			xDown=event.getRawX();
			break;

		case MotionEvent.ACTION_MOVE:
			// 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整menu的leftMargin值,从而显示和隐藏menu
		    xMove=event.getRawX();
		    int distanceX=(int) (xMove-xDown);
		    if(isMenuVisible){
		    	menuParams.leftMargin=distanceX;
		    }else {
		    	menuParams.leftMargin=distanceX+leftEdge;
		    }if(menuParams.leftMargin<leftEdge){
		    	menuParams.leftMargin=leftEdge;
		    }else if(menuParams.leftMargin>rightEdge){
		    	menuParams.leftMargin=rightEdge;
		    }
		    menu.setLayoutParams(menuParams);
		    break;
		case MotionEvent.ACTION_UP:
			// 手指抬起时,进行判断当前手势的意图,从而决定是滚动到menu界面,还是滚动到content界面
			xUp=event.getRawX();
			if(wantToShowMenu()){
				if(shouldShowMenu()){
					ScollToMenu();
				}else {
					ScollToContent();
				}
			}
			else if(wantToShowContent()){
				if(shouldShowContent()){
					ScollToContent();
				}else {
					ScollToMenu();
				}
			}
			break;
		}
		recycleVelocityTracker();
		return true;
	}
	private boolean wantToShowMenu(){
		return xUp-xDown > 0 && !isMenuVisible;
	}
	private boolean wantToShowContent(){
		return xUp-xDown < 0 && isMenuVisible;
	}
	private boolean shouldShowMenu(){
		return xUp-xDown > screenWidth/2 || getScrollVelocity() > SPEED;
	}
	private boolean shouldShowContent(){
		return xDown-xUp + menuPadding >screenWidth/2 || getScrollVelocity() > SPEED ;
	}
	private void ScollToMenu(){
		new ScrollTask().execute(30);
	}
	private void ScollToContent(){
		new ScrollTask().execute(-30);
	}
	/**
	 * 创建VelocityTracker对象,并将触摸content界面的滑动事件加入到VelocityTracker当中。
	 * 
	 * @param event
	 *            content界面的滑动事件
	 */
	private void createVelocityTracker(MotionEvent event){
		if(mVelocityTracker==null){
			mVelocityTracker=VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
	}
	private void recycleVelocityTracker(){
		mVelocityTracker.recycle();
		mVelocityTracker=null;
	}
	/**
	 * 获取手指在content界面滑动的速度。
	 * 
	 * @return 滑动速度,以每秒钟移动了多少像素值为单位。
	 */
	private int getScrollVelocity(){
		mVelocityTracker.computeCurrentVelocity(1000);
		int velocity=(int) mVelocityTracker.getXVelocity();
		return Math.abs(velocity);
	}
	class ScrollTask extends AsyncTask<Integer, Integer, Integer>{

		@Override
		protected Integer doInBackground(Integer... speed) {
			int leftMargin=menuParams.leftMargin;
			// 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。
			while(true){
				leftMargin=leftMargin+speed[0];
				if(leftMargin>rightEdge){
					leftMargin=rightEdge;
					break;
				}
				if(leftMargin<leftEdge){
					leftMargin=leftEdge;
					break;
				}
				publishProgress(leftMargin);
				//为了产生滑动效果,而睡眠20毫秒
				sleep(20);
			}
			if (speed[0] > 0) {
				isMenuVisible = true;
			} else {
				isMenuVisible = false;
			}
			return leftMargin;
		}
	    @Override
	    protected void onProgressUpdate(Integer... leftMargin) {
	    	menuParams.leftMargin=leftMargin[0];
	    	menu.setLayoutParams(menuParams);
	    }
	    
	    @Override
	    protected void onPostExecute(Integer leftMargin) {
	    	menuParams.leftMargin=leftMargin;
	    	menu.setLayoutParams(menuParams);
	    }
	}
	private void sleep(long mills){
		try {
			Thread.sleep(mills);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值