在前面的文章中有一系列的自定义 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 表示不消耗这个事件。
文字总是枯燥的,先来看看大图。
事件分发这里描述了一个点击事件的过程,那么现在来解释一下这张图:
- 一个点击事件发生之后,事件是现传给 Activity ,Activity 再传递给 Window ,Window 传递给 Top View,然后就是按照事件分发机制去进行。
- 如果一个 view 的 onTouchEvent() 返回 false ,则这个事件会传递给它的上一级处理,如果一直返回false ,最终会传递到 Activity 的 onTouchEvent() 进行处理。
- 一般情况下,一个事件只能被一个 view 消耗。当然,如果是某个 view 消耗了事件之后,又在 onTouchEvent() 中手动分发,这样就是另外一回事了。
- ViewGroup 默认不连接任何事件,ViewGroup 的 onInterceptTouchEvent() 默认返回 false 。
- view 默认没有 onInterceptTouchEvent() ,一但事件传递给它,就会调用 onTouchEvent() 。
- view 的 onTouchEvent() 默认都会消耗事件,除非是不可点击的(clickable 和 longclickable 同时为 false。
- 有些控件默认 clickable 为 true,例如 Button。有些默认为 false,例如 TextView。所以在设置点击事件的时候就要注意,有些时候不能设置点击事件,可能是因为这个。
- 子元素可以通过 requestDisallowInterceptTouchEvent() 干预父元素的事件分发。
参考文献:《Android开发艺术探索》
我的公众号
公众号内容描述
zone7 公众号,与您一起学习分享后端知识。本公众号涉及的知识点将会有:nodejs,python,docker,kubernetes,后端架构等
zone7
网友评论