[Android] 解决 View 滑动冲突法则
2016-03-05 20:09
423 查看
前言
这是 demo 地址上面 demo 用外部拦截法实现了滑动方向一致和不一致的两种冲突。
滑动冲突场景
场景 1————外部滑动方向和内部滑动方向不一致场景 2————外部滑动方向和内部滑动方向一致
场景 3————上面两种情况的嵌套
场景 1,主要是 ViewPager 和 Fragment 配合使用组成的页面横向滑动效果,而 Fragment 里又包含了 ListView 竖直滑动的控件。由于 ViewPager 里做了滑动冲突的处理,所以使用 ViewPager 时没有出现滑动冲突的现象。
场景 2,内外两层都在同一个方向可以滑动。比如,使用 ViewPager 和 Fragment 配合做页面横向滑动。在 Fragment 中使用 RecyclerView 做横向滑动效果。
场景 3,是场景 1 和场景 2 的结合。比如,使用 ViewPager 和 Fragment 配合做页面横向滑动,Fragment 中使用 ListView 做竖直方向的滑动,而 ListView 中的 item 中包含横向滑动的 RecyclerView。这种场景有些复杂,但有时在实际工作也会遇到,比如我公司项目锋绘动漫的首页就是这种场景。
滑动冲突的解决方式
外部拦截法
外部拦截法是指触摸事件先经过父容器的拦截处理,如果父容器需要此事件就拦截,否则不拦截。外部拦截法需要重写父容器的 onInterceptTouchEvent 方法,在此方法中做相应的拦截即可,伪代码如下:@Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercept = false; int x = (int) ev.getX(); int y = (int) ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: intercept = false; break; case MotionEvent.ACTION_MOVE: int dealtX = x - mInterceptX; int dealtY = y - mInterceptY; if(父容器需要当前事件){ intercept = true; }else{ intercept = false; } break; case MotionEvent.ACTION_UP: intercept = false; mInterceptX = mInterceptY = 0; break; } return intercept; }
在 onInterceTouchEvent 方法中,ACTION_DOWN 事件,父容器必须返回 false,因为一旦父容器拦截了 ACTION_DOWN,那么后续的 ACTION_MOVE 和 ACTION_UP 都会直接交由父容器处理,事件无法再传递给子元素。ACTION_UP 也必须返回 false,因为如果父容器 ACTION_UP 返回 true,就导致子元素无法接受 ACTION_UP,子元素中的 onClick 事件也就无法触发了。
内部拦截
内部拦截是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器处理。这种方法和 Android 的事件分发机制不一致,需要配合 requestDisallowInterceTouchEvent 方法才能正常工作。我么需要重写子元素的 dispatchTouchEven 方法,伪代码如下:@Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: if (父容器需要此事件){ getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; } return super.dispatchTouchEvent(ev); }
上述代码是内部拦截的典型代码,当面对不同的互动策略时只需要修改里面的条件即可。除了子元素需要做处理父元素也要重写 onInterceptTouchEvent 方法,拦截除了 ACTION_DOWN 以外的其他事件,这样当子元素调用 getParent().requestDisallowInterceptTouchEvent(false) 时,父元素才能拦截所需要的事件。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories