Android View的事件分发详解
1.前言
近两天学习了一下view的事件分发,把自己的理解总结了一遍,只表达了自己认为需要明白的地方,毕竟是菜鸟一枚,不对的地方还请大神们多指教!
2.三个方法
public boolean dispatchTouchEvent(MotionEvent ev)
用于事件的分发,返回结果受以下两个方法的影响,表示是否消耗了事件。
public boolean onInterceptTouchEvent(MotionEvent ev)
事件是否被拦截,返回true表示拦截,false表示不拦截
public boolean onTouchEvent(MotionEvent ev)
表示事件是否被处理
3.三个方法之间的关系
public boolean dispatchTouchEvent(MotionEvent ev){ boolean result = false; if(onInterceptTouchEvent(ev)){ result = onTouchEvent(ev); }else{ result = child.dispatchTouchEvent(ev); } return result; }
4.原理论述
1.同一个事件序列是指从手指接触屏幕开始到离开屏幕那一刻产生的一系列事件,其中以down开始,中间产生若干move事件,最后以up事件结束。
2.同一个事件序列,只能被一个view拦截处理,如果它不消耗down事件,那么其他的事件也不会交给它处理,而且一旦它处理了down事件,以后的事件便不会调用onInterceptTouchEvent此方法判断是否拦截,因为都会交给它处理,就不用再询问了。
3.如果view不消耗除down以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前view可以持续接收后续事件,最终这些消失的点击事件将交由activity处理。
4.ViewGrop默认不拦截任何事件。
5.VIew没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会调用。
6.View处于不可点击状态时(clickable和longClickable同时为false),onTouchEvent不会消耗事件。除此之外onTouchEvent默认都是消耗事件返回为true的。
7.View的enable属性不影响onTouchEvent的默认返回值
8.事件的传递过程是由外向内的,即事件都是先传递给父元素然后再分发给子元素。通过requestDisallowInterceptTouchEvent方法干预父元素的事件分发过程,但是ACTION_DOWN事件除外。
9.view中的点击事件优先级,高-低:onTouchListener--->onTouchEvent--->onClickListener,当onTouchListener中的onTouch方法返回false时,onTouchEvent才会调用
5.个别源码分析
这是ViewGroup的dispatchTouchEvent中拦截事件的一段源码,主要讲述拦截过程的思路
1.mFirstTouchTarget 表示当事件被ViewGroup的子元素成功处理时,会被赋值,所以一旦ViewGroup拦截事件,则mFirstTouchTarget ==null,则返回true。
2FLAG_DISALLOW_INTERCEPT此标志位是有requestDisallowInterceptTouchEvent方法设置的,一般位于子view中,一旦此标志位设置则不会执行VIewGroup中的onInterceptTouchEvent方法,也就不会拦截除了ACTION_DOWN之外的方法,印证了论述2
// Check for interception. final boolean intercepted; if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) { final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed } else { intercepted = false; } } else { // There are no touch targets and this action is not an initial down // so this view group continues to intercept touches. intercepted = true; } ... // Check for cancelation. final boolean canceled = resetCancelNextUpFlag(this) || actionMasked == MotionEvent.ACTION_CANCEL;
相关文章
Android 进入Activity时如何禁止弹出软键盘输入法
这篇文章主要介绍了Android 进入Activity时如何禁止弹出软键盘输入法,文章围绕主题展开具体内容,需要的小伙伴可以参考一下2022-05-05Android Zipalign工具优化Android APK应用
本文主要介绍Android Zipalign工具优化Android APK应用,这里整理了相关资料及简单优化实例,有需要的小伙伴可以参考下2016-09-09Android RadioButton 图片位置与大小实例详解
这篇文章主要介绍了Android RadioButton 图片位置与大小实例详解的相关资料,这里提供实例代码及实现效果图,需要的朋友可以参考下2016-11-11Android NotificationManager简单使用详解
这篇文章主要为大家详细介绍了Android NotificationManager的简单使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2021-11-11Android组件之BroadcastReceiver广播接收者
这篇文章主要为大家介绍了Android组件之BroadcastReceiver广播接收者实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-04-04Android ImageView 不显示JPEG图片的问题解决
本篇文章主要介绍了Android ImageView 不显示JPEG图片及Android Studio中如何引用图片资源的相关知识,具有很好的参考价值。下面跟着小编一起来看下吧2017-05-05
最新评论