Android事件分发机制以及滑动冲突处理
来源:互联网 发布:python proxyfix 编辑:程序博客网 时间:2024/05/06 02:50
http://blog.csdn.net/u013038616/article/details/50733811
方便日后的查看与交流,将学习与实践总结如下。
一、Android事件传递分析
1、ViewGroup中事件分发机制相关的方法a、dispatchTouchEvent 事件分发器
b、onInterceptTouchEvent 处理是否拦截事件
c、onTouchEvent处理对应的事件
ViewGroup中他们的代码关系如下伪代码表示:
常用结论:
a、一个完整的MotionEvent由DOWN(1)->MOVE(n>=0)->UP(1)构成
b、一旦onInterceptTouchEvent拦截了某类事件,该onInterceptTouchEvent方法只会调用一次,后续该事件默认交给该View执行。例如某ViewGroup拦截了DOWN事件,后面的MOVE(n>=0)->UP(1)就默认由该ViewGroup处理,不会向下传递。
c、事件的传递方向:由父容器传向子View,即由外到内。
d、View中没有onInterceptTouchEvent()方法,View默认自己处理事件。
e、ViewGroup的onInterceptTouchEvent()方法默认返回false,即不拦截任何事件。
2、事件分发过程相关类和方法的源码
a、事件传递的大体过程
Activity->Window->View
b、Activity的事件分发器源代码
c、Window的superDispatchTouchEvent(ev)方法
DecorView的类定义如下:
因为DecorView也是ViewGroup所以事件分发的过程和ViewGroup的事件分发过程类似。
d、View中dispatchTouchEvent方法主要的分发逻辑
注意:View不是ViewGroup不需要向其子View进行事件分发,所以View中没有onInterceptTouchEvent方法,事件将直接交给OnTouchListener的onTouch或ViewGroup的onTouchEvent方法处理,且OnTouchListener会屏蔽onTouchEvent方法。e、ViewGroup中dispatchTouchEvent方法主要的分发逻辑
ViewGroup的分发代码比较复杂,暂不列出,有兴趣的话可以去看看源码。
3、一个完整的事件分发过程(该事件的起点区域必须有重叠的子View,父容器才会进行事件分发,否则
父类将自己处理该事件的全部过程)
a、事件先传递给Activity的public boolean dispatchTouchEvent(MotionEvent ev)
b、Activity先 将事件交给Window类的superDispatchTouchEvent(ev)处理
c、Window类再将事件交给顶级View(DecorView)进行事件传递处理
d、顶级View(DecorView)将事件传递给我们定义的布局文件中View(一般为ViewGroup)处理,如果处
理则将事件,即ViewGroup的onInterceptTouchEvent方法返回true,则事件有该ViewGroup处理,如果设
置了setOnTouchEventListener,那么将调用onTouch方法,否则调用其onTouchEvent方法。如果setOnClickListener
点击事件则点击事件被调用;如果不处理该事件,则该事件将向下传递给其子View,调用子View的
dispatchTouchEvent方法,依次处理直到事件被处理,如果最终未处理则进行e。
e、getWindow().superDispatchTouchEvent(ev)返回了false就说明没有View处理该事件,事件将最
终传递给Activity的onTouchEvent进行处理。
二、处理View的滑动冲突
1、滑动冲突的分类
滑动冲突的解决方法是根据上面事件传递的机制进行处理的,熟练掌握事件分发机制是处理滑动冲突的前提。然后就是根据不同的规则来重写View的onInterceptTouchEvent方法,来决定什么时候让父容器拦截滑动事件什么时候让子View拦截滑动事件。
滑动冲突大致可分以下两类:
1、两层滑动嵌套的情况:
a、外层与内层的滑动方向垂直
b、外层与内层的滑动方向平行
2、多层滑动嵌套的情况:可以转化为两层的情况进行处理
滑动冲突的处理方式可分以下两类:
a、外部拦截法:所有事件都要经过父容器,如果父容器需要此事件就进行拦截,不需要就不拦截。
b、内部拦截法:所有事件都传递给子View,如果子View需要此事件就直接消耗,如果不需要就交给
父容器处理。该方法与原有的分发顺序不一样,需要配合parent.requestDisallowInterceptTouchEvent()进行事件重新分发才能正常工作。
2、滑动冲突的实例解决方案
滑动冲突第一类中的第一种的解决方法如下:
如父容器需要左右滑动,而子View需要上下滑动(如ViewPager的情况)。这个解决方法很简单也很典型,直接可以通过用户的滑动来判断用户的意图。通过判断手指在屏幕上移动一小段距离,计算出x轴上的增量dx,y轴上的增量dy,比较dx与dy绝对值的大小,如果dx>dy说明用户想左右滑动;反之,是想上下滑动。这是最直接的一种判断方法,还可以根据滑动方向与水平方向的夹角判断,总之能正确区分用户的意图即可。
a、采用外部拦截法
然后根据上面的规则重写父容器的onInterceptTouchEvent方法,子View不用做任何求改。如下:
b、采用内部拦截法
该方法需要改变事件的分发顺序,所以需要重写子View的dispatchTouchEvent方法。根据上面的规则子View的dispatchTouchEvent方法改写如下:
注意:其中parent为该View需要拦截滑动事件的那个父容器的引用。
父容器也要做相应的修改:
父容器需要拦截处理ACTION_DOWN以外的所有事件。然后通过在子View中调用requestDisallowInterceptTouchEvent方法来控制父容器是否截断事件。
这里父容器如果拦截ACTION_DOWN事件,那么整个事件将交给父容器处理,子View将接受不到任何事件,从而不能进行内部拦截。
滑动冲突第一类中的第二种的解决方法和第一种的解决方法类似,虽然不能从用户点击屏幕的操作直接判断出用户的意图,但是可以根据不同的业务逻辑加以区分,只要能确定什么时候让父容器截获事件什么时候子View截获事件,就将上面方法的标注部分就行相应的修改即可处理此类冲突。
第二类处理起来比较复杂一些,需要将多层的冲突分解为第一类中单个的事件冲突,对单个的事件冲突再进项逻辑判断上的处理,就可将大化小,一层一层的处理冲突,即可解决此类滑动冲突。
- Android事件分发机制以及滑动冲突处理
- Android事件分发机制以及滑动冲突处理
- Android事件分发机制以及滑动冲突处理
- Android事件分发机制及滑动冲突处理的几篇博文
- Android事件分发机制与滑动冲突
- 【Android View事件分发机制】滑动冲突
- Android事件分发机制、滑动冲突解决
- android事件分发机制及冲突处理
- 通过事件分发机制处理ListView与ScrollView滑动冲突
- 通俗理解Android中View的事件分发机制及滑动冲突处理
- 菜鸟都能理解的Android中View的事件分发机制及滑动冲突处理
- Android自定义View探索(三)—事件分发机制与滑动冲突处理
- 通俗理解Android中View的事件分发机制及滑动冲突处理
- 【Android API】Android事件分发机制和滑动冲突
- Android 滑动冲突,事件分发机制的详解
- Android View事件分发机制及View的滑动冲突
- Android滑动冲突与事件分发机制浅析
- Android View的事件分发机制和滑动冲突解决方案
- 二叉树
- 计算几何总结
- Hadoop FIleSystem API JAVA操作。
- Q121:PBRT-V3,光传播方程(The Light Transport Equation)(14.4章节)
- 剑指offer:(37)时间效率和空间效率的平衡 :两个链表的第一个公共结点
- Android事件分发机制以及滑动冲突处理
- JAVA:二进制与十进制转换
- What is a Servlet?
- 牛客网_华为机试_023_删除字符串中出现次数最少的字符
- poj 3669 bfs
- [编程题] 微信红包
- 从join on和where执行顺序认识T-SQL查询处理执行顺序
- hadoop 日志及历史服务器
- 类的动态分配内存与释放