话说:只要掌握了事件分发机制,就能找到好工作、升职加薪、当上总经理、出任ceo、迎娶白富美。
哈哈哈,不啰嗦,让我们开始。
三个重要的方法
和事件分发机制密切相关的三个方法分别是:
public boolean dispatchTouchEvent(MotionEvent ev)
用来进行事件的分发。如果事件能够传递到当前View,此方法一定会被调用,返回结果受当前View的onTouchEvent()
和下级View的diapatchTouchEvent()
方法的影响,表示是否消耗当前事件。
public boolean onInterceptTouchEvent(MotionEvent event)
用来判断是否拦截某个事件,如果当前View拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
public boolean onTouchEvent(MotionEvent event)
在dispatchTouchEvent()
中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收事件。
三个方法之间的联系:
public boolean dispatchTouchEvent(MotionEvent event) {
boolean consume = false;
if(onInterceptTouchEvent(ev)) {
consume = onTouchEvent(ev);
} else {
consume = child.dispatchTouchEvent(ev);
}
return consume;
}
通过上面的伪代码,我们大致可以了解点击事件的传递规则:对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,这是它的
dispatchTouchEvent()
就会被调用,如果这个ViewGroup的onInterceptTouchEvent()
方法返回true就表示它要拦截当前事件,接着事件就会交给该ViewGroup处理,即执行onTouchEvent()
方法。如果onInterceptTouchEvent()
方法返回false就表示它不拦截该当前事件,这时事件就会继续传递给它的子元素,接着子元素的dispatchTouchEvent()
就会被调用,如此反复,直到事件被处理。
一些结论(摘抄自《Android开发艺术探索》)
同一个事件序列是指从手指触摸屏幕的那一刻起,到手指离开屏幕那一刻结束,在这个过程中产生的一系列事件,这一系列事件以down事件开始,以up事件结束,中间可能有一些move事件。
正常情况下,一个事件序列只能被一个View拦截并消耗。
某个View一旦决定拦截,那么这一个事件序列都只能由它来处理(如果事件序列能够传递给它的话),并且它的
onInterceptTouchEvent()
不会再被调用。某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(
onTouchEvent()
返回了false),那么同一事件序列中的其他事件都不会再交给它处理,并且事件将重新交由它的父元素去处理,及父元素的onTouchEvent()
会被调用。如果View不消耗ACTON_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent()并不会被调用,并且当前View可以持续收到后续的事件。最终这些消失的点击事件会传递给Activity处理。
ViewGroup默认不拦截事件。
onInterceptTouchEvent()
方法默认返回false。View没有
onInterceptTouchEvent()
方法,一旦有事件传递给它,那么它的onTouchEvent()
方法就会被调用。View的
onTouchevent()
默认都会消耗事件(返回true),除非它是不可点击的(clickable和longClickable同时为false)。View的enable属性不影响
onTouchEvent()
的默认返回值。哪怕一个View是disable状态的,只要它的clickable和longClickable有一个为true,那么它的onTouchEvent()
就返回true。onClick会发生的前提是当前View是可点击的,并且它收到了down和up的事件。
事件传递的方向是由外向内的,即事件总是先传递给父元素,然后由父元素分发给子View。
当面对ACTION_DOWN事件时,ViewGroup总是会调用自己的
onInterceptTouchEvent()
方法来询问自己是否要拦截该事件。当ACTION_UP方法发生时,会触发
performClick()
方法,如果View设置了onClickListener,那么performClick()
方法内部会调用它的onClick()方法。
流程图
为了把事件分发机制研究明白,我画了一张流程图。
就到这里了。
如果有什么问题,大家可以在评论中提出来,我们一起讨论。
加油,各位!
本文来自:http://qiaoyunrui.github.io/2016/05/23/androidDispatchEvent/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。