Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理


《Android 滑动侧边栏(Sliding Menu)实现分析》

《Android 滑动侧边栏(Sliding Menu)第一种实现 - 1 手动滚动+自动滚动》

《Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理》(本篇文章)

《Android 滑动侧边栏(Sliding Menu)第二种实现方式1》




一、 有图有真相

Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理_第1张图片


二、分析与伪码

1. 添加onIntercepteEvent, 只有当手指在右侧视图上并且移动超过一定距离,满足这连个条件拦截交由ViewGoup执行滚动

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		
		final int actioin = ev.getAction();
		final int x = (int) ev.getX();
		
		switch (actioin) {
		case MotionEvent.ACTION_DOWN:
			mInterceptMotionX = x;
			break;

		case MotionEvent.ACTION_MOVE:
			final int deltaX = x - mInterceptMotionX;
			final int distance = Math.abs(deltaX);
			// 点击区域必须在右侧视图,因为仅右侧视图可移动
			// 横向移动超过一定距离,可以自己根据需求改动
			if ( canSliding(ev) && distance > mTouchSlop * 2) {

				// 置为初始值
				mLastX = x;
				if (mScrollRunnable != null) {
					mScrollRunnable.endScroll();
					mScrollRunnable = null;
				}
				
				// 拦截Touch Event 交由当前ViewGruop onTouchEvent处理
				return true;
			}
			
			break;
			
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:	
			mInterceptMotionX = 0;
			break;
		}
		
		return false;
	}

2. 上面用到的判断是否是右侧视图改变canSliding方法内部实现改变,使用ViewGroup.dispatchTouchEvent中判断方式。

	/**
	 * 当前手指点击位置是否在右侧视图区域内
	 * 
	 * @param event
	 * @return true 可以滚动
	 */
	private boolean canSliding(MotionEvent event) {
		
		final int scrolledXInt = (int) (event.getX() + getScrollX());
		final int scrolledYInt = (int) (event.getY() + getScrollY());
		
		Rect frame = new Rect();
		mRightView.getHitRect(frame);
		if (frame.contains(scrolledXInt, scrolledYInt)) {
			return true;
		}
		
		return false;
	}


3. 改变onTochEvent,ACTION_DOWN的处理放到onInterceptTouchEvent中了,而且ViewGroup也不需要拦截DOWN事件,所以DOWN事件从onTochEvent删除。

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		
		final int x = (int) event.getX();
		
		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			
			scrollIfNeed(x);
			return true;
			
		case MotionEvent.ACTION_UP:
			
			autoScrollIfNeed(x);
			break;
		}
		
		return false;
	}

4. scrollIfNeed方法改变,右侧视图盖住左侧视图时,隐藏左侧视图,目的是为了此时左侧视图不接收Touch Event

	private void scrollIfNeed(final int x) {
		// 计算与上次的偏移量
		int deltaX = x - mLastX;
		
		// 减少移动次数
		if (x != mLastX) {
			// 显示
			if (mLeftView.getVisibility() != View.VISIBLE) {
				mLeftView.setVisibility(View.VISIBLE);
			}
			
			int l = mRightView.getLeft();
			int t = mRightView.getTop();
			int b = mRightView.getBottom();
			
			// 右侧视图的滑动区域,只能在左侧视图范围内滑动
			int rightViewLeft = Math.max(mLeftView.getLeft(), l + deltaX);
			rightViewLeft = Math.min(mLeftView.getRight(), rightViewLeft);
			
			// 控制随手指滑动
			mRightView.layout(rightViewLeft, t, rightViewLeft + mRightView.getWidth(), b);
		}
		
		// 滑动到最左侧
		if (mRightView.getLeft() == mLeftView.getLeft()) {
			mLeftView.setVisibility(View.INVISIBLE);
		}
		
		// 记录当前值供下次计算		
		mLastX = x;
	}


三、完整源码下载

源码下载地址



    本文只是一个待完善的DEMO,如果想更深入学习的可以看下GITHUB上的SlidingMenu实现  https://github.com/jfeinstein10/SlidingMenu 


原文地址:http://blog.csdn.net/love_world_/article/details/8666210


2013-04-17   添加开源实现链接


你可能感兴趣的:(Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理)