android view(5) 事件机制

参考
Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

一、viewgroup向子元素传递事件

当一个MotionEvent产生后,系统要把这个事件传递给具体的view,这个传递过程就是分发。传递过程遵循如下顺序:Activity>Window>View,即事件总是先传递给Activity,然后到PhoneWindow,最后再传递给顶级view(一般是个viewgroup)。
顶级view收到事件后,会调用它的dispatchTouchEvent,伪代码如下:
<pre>
public boolean dispatchTouchEvent(MotionEvent event){
boolean consume = false;
if(onInterceptTouchEvent(event)){
consume = onTouchEvent(event);
}else{
consume = child.dispatchTouchEvent(event);
}
return consume;
}
</pre>

解释一下:
如果viewgroup的onInterceptTouchEvent事件返回true,就会去执行自己的onTouchEvent事件,表示自己拦截处理;相反的,如果onInterceptTouchEvent返回false,则表示自己不处理,dispatchTouchEvent交给子元素继续本过程,如此反复直到事件被处理。

同一个事件序列是指从手指接触屏幕那一刻起,到手指离开屏幕那一刻结束,这个过程中产生的一系列事件,以down事件开始,中间含有数量不定的move事件,最终以up事件结束。

下面是dispatchTouchEvent具体代码:
<pre>
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);
}else{
intercepted = false;
}else{
intercepted = true;
}
</pre>

也就是说,viewgroup会在两种情况下判断是否要拦截当前事件:事件类型为ACTION_DOWN或者mFirstTouchTarget != null。从后面逻辑看出,当事件由viewgroup子元素成功处理时,mFirstTouchTarget会指向这个子元素。也就是说,如果自己处理了,那么这个条件就不会满足。后续的ACTION_MOVE和ACTION_UP事件因为这个条件不满足,就不会再去执行onInterceptTouchEvent。
结论就是,一个事件序列只能被一个view拦截并消耗。当一个view决定拦截一个事件后,系统就会把同一个事件序列中的其他方法都交给它来处理,不会再调用onInterceptTouchEvent事件去询问它是否要拦截。

ViewGroup默认不拦截任何事件,其onInterceptTouchEvent方法默认返回false.
View没有onInterceptTouchEvent事件,一旦有点击事件传递给它,onTouchEvent就会被调用。onTouchEvent默认会消耗掉事件(返回true),enable属性不会影响这个默认值,除非clickable和longClickable同时为false.

二、view处理事件
  • view会先判断有没有设置onTouchListener,如果onTouchListener中的onTouch事件返回了true,那么view自己的onTouchEvent就不会被调用。这样的好处是方便在外界处理点击事件。

  • 在onTouchEvent中会处理点击事件。当ACTION_UP发生时,如果view设置了onClickListener,会调用其onClick方法。这里也可以看出,onClickListener优先级最低,处于事件传递的尾端。

  • 如果view的onTouchEvent事件返回false,那么同一事件序列的其他事件也不会再交给它处理,事件会重新交给父元素的onTouchEvent。点击事件就像一个难题,经过一系列事件分发过程,领导指定了一个程序员view去处理。但是这个程序员搞不定,在onTouchEvent中返回了false.那上级就不敢再把后续事件交给这个程序员处理了。事件会重新交给上一级,如果上一级也搞不定,会一层层往上抛,最终返回给activity的onTouchEvent来处理。

看一个例子:
<pre>
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick execute");
}
});
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "onTouch execute, action " + event.getAction());
return false;
}
});
</pre>

点击的时候,会输出什么呢:
onTouch execute action 0
onTouch exxecute action 1
onClick execute

根据上面的结论,很容易分析到OnTouchListener会最先执行,因为onTouch返回了false,所以onTouchEvent会接着执行。如果有onClickListener,又会去执行。那么如果onTouch返回true呢,事件就被消耗了,显然onClick方法就不会去执行了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容