Android进阶-view 的事件分发机制

在前面的文章中有一系列的自定义 view 的文章,
Android自定义View-水波纹progressbar
Android自定义View-刮刮卡效果
Android自定义View-蜘蛛网属性图(五边形图)
Android自定义View- 雷达扫描图
为了更好地学习自定义 view,有必要学习事件分发机制, 这也是 Android 面试中经常会被问到的。
事件分发机制相关的方法有三个,分别是:

dispatchTouchEvent(MotionEvent event);
用于进行事件的分发。如果事件能够传递给当前 view,那么此方法一定会被调用,返回结果受到当前 view 的 onTouchEvent() 和下级 view 的dispatchTouchEvent() 方法的影响,表示是否消耗当前事件。

onInterceptTouchEvent(MotionEvent event);
在 dispatchTouchEvent() 内部调用,由来判断是否拦截某个事件,如果某个 view 拦截了某个事件,则一般情况下不会继续往下传递了,此方法也不会再次被调用了。返回 true 表示拦截事件,进一步交由 onTouchEvent() 处理,返回 false 表示不拦截当前事件。

onTouchEvent(MotionEvent event);
在 dispatchTouchEvent() 内部调用,由于处理点击事件,返回 true 表示消耗这个事件,返回 false 表示不消耗这个事件。

文字总是枯燥的,先来看看大图。

事件分发
这里描述了一个点击事件的过程,那么现在来解释一下这张图:

  1. 一个点击事件发生之后,事件是现传给 Activity ,Activity 再传递给 Window ,Window 传递给 Top View,然后就是按照事件分发机制去进行。
  2. 如果一个 view 的 onTouchEvent() 返回 false ,则这个事件会传递给它的上一级处理,如果一直返回false ,最终会传递到 Activity 的 onTouchEvent() 进行处理。
  3. 一般情况下,一个事件只能被一个 view 消耗。当然,如果是某个 view 消耗了事件之后,又在 onTouchEvent() 中手动分发,这样就是另外一回事了。
  4. ViewGroup 默认不连接任何事件,ViewGroup 的 onInterceptTouchEvent() 默认返回 false 。
  5. view 默认没有 onInterceptTouchEvent() ,一但事件传递给它,就会调用 onTouchEvent() 。
  6. view 的 onTouchEvent() 默认都会消耗事件,除非是不可点击的(clickable 和 longclickable 同时为 false。
  7. 有些控件默认 clickable 为 true,例如 Button。有些默认为 false,例如 TextView。所以在设置点击事件的时候就要注意,有些时候不能设置点击事件,可能是因为这个。
  8. 子元素可以通过 requestDisallowInterceptTouchEvent() 干预父元素的事件分发。

参考文献:《Android开发艺术探索》

猜你喜欢

转载自blog.csdn.net/zone_/article/details/72819468