Android滑动冲突解决方案
来源:互联网 发布:linux ip 编辑:程序博客网 时间:2024/05/13 10:39
在App中,可以滑动的控件随处可见(viewPager,listView),毕竟在移动设备上,屏幕就那么大,要想给用户呈现更多的内容,我们的view就得支持滑动了,多个可以滑动的View嵌套在一起,就会引发一个问题,那就是一个事件(MotionEvent)到来时,到底哪一个view响应呢?这时应用的选择困难症犯病了,它会变得抓狂,我们的应用就会失常,这时我们要做的就是帮助它做出选择。废话不多说,下面我们就分析一下不同场景下滑动冲突的解决方案(全是套路啊)。滑动冲突是View体系中一个深入的话题,理解滑动冲突的解决方法,需要对view的事件分发体制有一定的了解。
滑动冲突场景
滑动嘛,不是左右滑动,就是上下滑动,冲突场景无非就是这两种情况的组合,最常见的冲突场景主要有以下三种:(1)内外两层view滑动方向不同
这种冲突场景也是最简单的一种了,在这里,外层view为水平方向的scrollView,内层view为listview。下面就用“外部拦截法”和“内部拦截法”分别对这种情景进行分析。① 外部拦截法:可想而知,这种方法是对外部view做处理,内部view不需做处理。由外部view来决定事件是否传递到内部view(当然,事件得能传递到外部view),如果外部view决定消耗此事件,则外部view进行事件拦截,反之,外部view不拦截事件,将事件传递到内部view进行处理。需要说一下,处理滑动冲突的策略并不是唯一的,只要可以解决问题即可,对于此种冲突场景,制定如下处理策略:我们可以计算滑动在x,y方向上的偏移量(当然也可以通过滑动角度),如果abs(dx)>abs(dy),说明用户左右滑动的趋势较为明显,外层view拦截并消耗事件,若abs(dx)<abs(dy),说明用户上下滑动的趋势较为明显,外层view不拦截事件,由内层view处理事件。我们需要实现外层view的InterceptTouchEvent(MotionEvent ev),来决定是否拦截事件。
float latestX; float latestY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean isIntercept = false; switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: isIntercept = false; break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(ev.getRawX() - latestX); float dy = Math.abs(ev.getRawY() - latestY); if (dx > dy) { isIntercept = true; } else { isIntercept = false; } break; case MotionEvent.ACTION_UP: isIntercept = false; break; } latestX = ev.getRawX(); latestY = ev.getRawY(); return isIntercept; }
② 内部拦截法: 外层view默认不拦截,由内层view决定事件是由自己消耗掉还是推给外层view处理,这种方法外层view和内层view都需要做处理。外层view需要实现onInterceptTouchEvent(MotionEvent ev),内层view需要实现dispatchTouchEvent(MotionEvent ev)。 外层view:
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean isIntercept = false; if (ev.getAction() == MotionEvent.ACTION_DOWN) { isIntercept = false; } else { isIntercept = true; } return isIntercept; }
内层view:
float latestX; float latestY; @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(ev.getRawX() - latestX); float dy = Math.abs(ev.getRawY() - latestY); if (dx > dy) { getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; latestX = ev.getRawX(); latestY = ev.getRawY(); return super.dispatchTouchEvent(ev); }
(2)内外两层view滑动方向相同
处理这种冲突,就需要视业务需求而看了,我们的业务需求决定什么条件下让外层view消耗事件,什么条件下让内层view消耗事件,核心思想与上面的情景很类似,就是决定条件发生变化而已,这里就不重复了。
(3)上面两种的组合
这种多重嵌套的情景就更复杂了,但是,归根结底,其处理思想与第一种相似,就需要看具体业务需求了。
1 0
- Android-滑动冲突解决方案
- Android滑动冲突解决方案
- android滑动冲突解决方案
- Android滑动冲突解决方案
- Android双向滑动冲突解决方案
- android滑动冲突的解决方案
- android滑动冲突的解决方案
- Android --- ListView 与 子项中滑动冲突解决方案
- android双向滑动冲突处理及解决方案
- Android中滑动冲突的解决方案
- android View滑动冲突的终极解决方案
- 滑动冲突的解决方案
- Android 开发中scrollview嵌套webview滑动冲突的解决方案
- Android scrollview嵌套webview滑动冲突的解决方案
- Android开发——View滑动冲突解决方案
- Android View的事件分发机制和滑动冲突解决方案
- Android Viewpager与WebView轮播滑动冲突的解决方案
- Android 开发中scrollview嵌套webview滑动冲突的解决方案
- 链栈的实现并解决行编辑程序问题及问题总结
- Javascript 面向对象编程(一):封装 ——转自阮一峰博客
- mybatis教程
- 线程与进程
- 3 红色警报
- Android滑动冲突解决方案
- BZOJ代码大全
- 九度OJ 1026 进制转换
- 使用 Redux 管理状态,第 3 部分: 使用 Redux 实现异步操作
- 一个程序员的提升
- two sum
- HUST1339-Reversal
- 数字三角形
- Qt显示pdf系列2——QAxWidget打开Office文件及pdf