首页 > 代码库 > Android自定义组件系列【15】——四个方向滑动的菜单实现

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)

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