《Android 滑动侧边栏(Sliding Menu)实现分析》
《Android 滑动侧边栏(Sliding Menu)第一种实现 - 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 添加开源实现链接