当前位置: 移动技术网 > 移动技术>移动开发>Android > Android的Touch事件处理机制介绍

Android的Touch事件处理机制介绍

2019年07月24日  | 移动技术网移动技术  | 我要评论
android的touch事件处理机制比较复杂,特别是在考虑了多点触摸以及事件拦截之后。
android的touch事件处理分3个层面:activity层,viewgroup层,view层。
首先说一下touch事件处理的几条基本规则。
如果在某个层级没有处理action_down事件,那么该层就再也收不到后续的touch事件了直到下一次action_down事件。

说明:
a.某个层级没有处理某个事件指的是它以及它的子view都没有处理该事件。
b.这条规则不适用于activity层(它是顶层),它们可以收到每一个touch事件。
c.如果没有处理action_move这类事件,不会有任何影响。

如果action_down事件发生在某个view的范围之内,则后续的action_move,action_up和action_cancel等事件都将被发往该view,即使事件已经出界了。
第一根按下的手指触发action_down事件,之后按下的手指触发action_pointer_down事件,中间起来的手指触发action_pointer_up事件,最后起来的手指触发action_up事件(即使它不是触发action_down事件的那根手指)。

pointer id可以用于跟踪手指,从按下的那个时刻起pointer id生效,直至起来的那一刻失效,这之间维持不变。
如果一个action_down事件被父view拦截了,则任何子view不会再收到任何touch事件了(这符合第1点的要求)。
如果一个非action_down事件被父view拦截了,则那些上次处理了action_down事件的子view会收到一个action_cancel事件,之后不会再收到任何touch事件了,即使父view不再拦截后续的touch事件。

如果父view决定处理touch事件或者子view没有处理touch事件,则父view按照普通view的处理方式处理touch事件,否则它根本不处理touch事件(它只负责分发)。
如果父view在onintercepttouchevent中拦截了事件,则onintercepttouchevent中不会再收到touch事件了,事件被直接交给它自己处理(按照普通view的处理方式)。
下面分层讲述一些细节。

1.activity层:
复制代码 代码如下:

public boolean dispatchtouchevent(motionevent ev) {
if (ev.getaction() == motionevent.action_down) {
onuserinteraction();
}
if (getwindow().superdispatchtouchevent(ev)) { //在这里交给view层处理
return true;
}
return ontouchevent(ev); // 如果view层没有处理,则在这里处理
}

2.view层:
复制代码 代码如下:

public boolean dispatchtouchevent(motionevent event) {
// 省略了部分细节
listenerinfo li = mlistenerinfo;
if (li != null && li.montouchlistener != null && (mviewflags & enabled_mask) == enabled
&& li.montouchlistener.ontouch(this, event)) {
return true;
}
if (ontouchevent(event)) {
return true;
}
return false;
}

view的ontouch方法代码比较多,主要的逻辑分两步:先是将事件交给touchdelegate处理(如果有的话),如果touchdelegate没有处理再自行处理;自行处理主要负责view状态的变换(如按下状态),长按事件,点击事件的检测与触发等。

3.viewgroup层(比较复杂):
viewgroup层处理touch事件的总体逻辑是:先检测是否需要拦截,没有拦截的话下发给子view处理,如果子view没有处理再自行处理,自行处理的逻辑与view一样。
拦截的逻辑是,将从down到up之间的所有事件看作一组事件,如果从down就拦截了,则组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了;如果是从中间拦截,则先给子view发送cancel事件,组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了。

分发的逻辑是,在action_down事件的时候,寻找子view进行处理,称为寻找target;如果没有找到target,则自行处理;如果找到target,则交由target处理。
从代码上看,dispatchtouchevent负责分发逻辑,ontouchevent负责真正的处理逻辑,一般应该重载ontouchevent,只有特殊情况下才需要重载dispatchtouchevent。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网