• Android自定义组件系列【15】——四个方向滑动的菜单实现


    今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下。

    一、效果演示

    (说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静态图片吧,实际效果可以下载源代码查看)


    (向上滑动)


    (向下滑动)


    (向左滑动)


    (向右滑动)

    二、实现过程介绍

    1、放置5个View (分别是上下左右中)

    	@Override
    	protected void onLayout(boolean changed, int l, int t, int r, int b) {
    		mTopView.layout(0, -mViewHeight, mViewWidth, 0);
    		mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
    		mCenterView.layout(0, 0, mViewWidth, mViewHeight);
    		mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
    		mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
    	}

    转载请说明出处:http://blog.csdn.net/dawanganban

    2、通过onTouchEvent事件来判断移动方向

    	private float mDownY;
    	private float mDownX;
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		int disY;
    		int disX;
    		float eventY = event.getY();
    		float eventX = event.getX();
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			mDownY = eventY;	
    			mDownX = eventX;
    			break;
    		case MotionEvent.ACTION_UP:
    			disY = (int)(eventY - mDownY);
    			disX = (int)(eventX - mDownX);
    			if(Math.abs(disY) > Math.abs(disX)){
    				if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
    					if(disY > 0){ //向下滑动
    						Log.d(TAG, "TO_BOTTOM");
    						changeToBottom();
    					}else{		  //向上滑动
    						Log.d(TAG, "TO_TOP");
    						changeToTop();
    					}
    				}
    			}else{
    				if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
    					if(disX > 0){ //向右滑动
    						Log.d(TAG, "TO_RIGHT");
    						changeToRight();
    					}else{		  //向左滑动
    						Log.d(TAG, "TO_LEFT");
    						changeToLeft();
    					}
    				}
    			}
    			break;
    
    		default:
    			break;
    		}
    		return true;
    	}
    3、通过computerScroll()方法实现平滑移动

    	@Override
    	public void computeScroll() {
    		super.computeScroll();
    		if(mScroller.computeScrollOffset()){
    			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    			postInvalidate();
    		}
    	}
    4、判断临界条件(否则会一直向一个方向滑动)

    		int[] location = new int[2];
    		mCenterView.getLocationOnScreen(location);
    		if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;
    例如上面代码就是判断向下滑动的临界条件,location[1]代表中间View的y坐标(相对于屏幕)。

    三、整个View的源码

    package com.example.testmx4update;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Scroller;
    
    /**
     * 自定义可以拖动的View
     * @author 阳光小强  http://blog.csdn.net/dawanganban
     *
     */
    public class MyCanPullView extends ViewGroup{
    	
    	private static final int MIN_VIEW_HEIGHT = 200;
    	private static final int MIN_VIEW_WIDTH = 400;
    
    
    	private static final String TAG = "TEST";
    	
    	
    	private int mViewHeight;
    	private int mViewWidth;
    	
    	private View mTopView;
    	private View mBottomView;
    	private View mCenterView;
    	private View mLeftView;
    	private View mRightView;
    	
    	
    	
    	private Scroller mScroller;
    
    	public MyCanPullView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		
    		initView(context);
    		
    		mScroller = new Scroller(context);
    	}
    
    	private void initView(Context context) {
    		setTopView(context);
    		setBottomView(context);
    		setCenterView(context);
    		setLeftView(context);
    		setRightView(context);
    	}
    	
    	
    	private float mDownY;
    	private float mDownX;
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		int disY;
    		int disX;
    		float eventY = event.getY();
    		float eventX = event.getX();
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			mDownY = eventY;	
    			mDownX = eventX;
    			break;
    		case MotionEvent.ACTION_UP:
    			disY = (int)(eventY - mDownY);
    			disX = (int)(eventX - mDownX);
    			if(Math.abs(disY) > Math.abs(disX)){
    				if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
    					if(disY > 0){ //向下滑动
    						Log.d(TAG, "TO_BOTTOM");
    						changeToBottom();
    					}else{		  //向上滑动
    						Log.d(TAG, "TO_TOP");
    						changeToTop();
    					}
    				}
    			}else{
    				if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
    					if(disX > 0){ //向右滑动
    						Log.d(TAG, "TO_RIGHT");
    						changeToRight();
    					}else{		  //向左滑动
    						Log.d(TAG, "TO_LEFT");
    						changeToLeft();
    					}
    				}
    			}
    			break;
    
    		default:
    			break;
    		}
    		return true;
    	}
    	
    	private void changeToBottom(){
    		int[] location = new int[2];
    		mCenterView.getLocationOnScreen(location);
    		if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;
    		int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
    		mScroller.startScroll(0, getScrollY(), 0, -dy, 500);
    		invalidate();
    	}
    	
    	private void changeToTop(){
    		int[] location = new int[2];
    		mTopView.getLocationOnScreen(location);
    		if(location[1] <= -mViewHeight - MIN_VIEW_HEIGHT / 2) return;
    		int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
    		mScroller.startScroll(0, getScrollY(), 0, dy, 500);
    		invalidate();
    	}
    	
    	private void changeToRight(){
    		int[] location = new int[2];
    		mCenterView.getLocationOnScreen(location);
    		if(location[0] >= mViewWidth - MIN_VIEW_WIDTH * 2) return;
    		int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
    		mScroller.startScroll(getScrollX(), 0, -dx, 0, 500);
    		invalidate();
    	}
    	
    	private void changeToLeft(){
    		Log.d(TAG, "TO_LEFT");
    		int[] location = new int[2];
    		mLeftView.getLocationOnScreen(location);
    		if(location[0] <= -mViewWidth - MIN_VIEW_WIDTH / 2) return;
    		int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
    		mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
    		invalidate();
    	}
    	
    	@Override
    	public void computeScroll() {
    		super.computeScroll();
    		if(mScroller.computeScrollOffset()){
    			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    			postInvalidate();
    		}
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int l, int t, int r, int b) {
    		mTopView.layout(0, -mViewHeight, mViewWidth, 0);
    		mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
    		mCenterView.layout(0, 0, mViewWidth, mViewHeight);
    		mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
    		mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    		//获取整个View的宽高
    		mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
    		mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
    	}
    	
    	private void setTopView(Context context){
    		View topButton = new View(context);
    		topButton.setBackgroundColor(Color.RED);
    		mTopView = topButton;
    		this.addView(mTopView);
    	}
    	
    	private void setBottomView(Context context){
    		View bottomButton = new View(context);
    		bottomButton.setBackgroundColor(Color.GREEN);
    		mBottomView = bottomButton;
    		this.addView(mBottomView);
    	}
    	
    	private void setCenterView(Context context){
    		View centerButton = new View(context);
    		centerButton.setBackgroundColor(Color.WHITE);
    		mCenterView = centerButton;
    		this.addView(mCenterView);
    	}
    	
    	private void setLeftView(Context context){
    		View leftButton = new View(context);
    		leftButton.setBackgroundColor(Color.BLUE);
    		mLeftView = leftButton;
    		this.addView(mLeftView);
    	}
    	
    	private void setRightView(Context context){
    		View rightButton = new View(context);
    		rightButton.setBackgroundColor(Color.YELLOW);
    		mRightView = rightButton;
    		this.addView(mRightView);
    	}
    }
    
    获取全部源代码,请加群在群共享中获取(142979499)

  • 相关阅读:
    展望2018
    Android按下home键后重新打开app进入主activity的问题
    RxJava整合Retrofit遇到的问题总结
    【总结】四种逆元的求法
    【NOIP模板汇总】I Am Me
    【总结】两类素数筛详解
    【NOIP2009】最优贸易
    【SHOI2002】滑雪
    【51NOD1398】等公交
    【复习总结】玫瑰人生 La Vie en Rose
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468548.html
Copyright © 2020-2023  润新知