可能因为源代码性能优先原则,所以感觉这里源代码的可读性完全不及格.
但是要清晰流程必须阅读源代码,
以其花费好几天时间。看别人的文章10篇。还是模模糊糊。
还不如花一天时间,看源代码并自己测试。来的更有效率。
首先<
这个递归,最起码缺少consume为false的情况没有处理哇。只完成了递归的逻辑,但是false的后续处理呢? 需要自己再次调用onTouchEvent. public boolean dispatchTouchEvent(MotionEvent ev) { boolean consume = false; if (onInterceptTouchEvent(ev)) { consume = onTouchEvent (ev) ; } else { consume = child.dispatchTouchEvent (ev) ; if(consume==false) {consume = onTouchEvent (ev) ; } } return consume; }
自己简化的流程。
public boolean dispatchTouchEvent(MotionEvent ev) { boolean consume = false; int action=ev.getAction()& MotionEvent.ACTION_MASK; if(action==down || needgoChild)//down事件无条件进行递归检测,如果不是down事件,那么需要传递给下层的话。也判断一下。 { intercepted=onInterceptTouchEvent(ev); } else//这里意思就是非down的事件,没有下层需要处理,因为是要自己处理的。直接截断。 { intercepted=true; } if (intercepted ) { consume = onTouchEvent (ev) ;//消费逻辑A。 } else { if(action==down) { target child=xxx;循环子控件找到child. if(child==view)//子控件view消费掉 { consume =chilld.onTouchEvent (ev) ; } elseif(child==groupview)//递归进去 { consume = child.dispatchTouchEvent (ev) ; } else if(child==null){}//什么不不做。consume是默认值false. if(consume==false)//这里不能少,递归回来或没有触摸的子控件需要判断是否消费了,没有消费,自己要消费掉。源码是 判断mFirstTouchTarget这个值是否为null. { consume = this.onTouchEvent (ev) ; } } else { target child=xxx;//直接取出child. 这里不需要找child了。down已经找过一次了. if(child==view)//子控件view消费掉 { consume =chilld.onTouchEvent (ev) ; } elseif(child==groupview)//递归进去,递归逻辑A { consume = child.dispatchTouchEvent (ev) ; } else if(child==null){}//不可能到这里,应该会从递归逻辑A到消费逻辑A。 } } return consume; }
分析过程
一。自己的总结。 从大的说,其实就是一个递归。down的目的就是找到谁来处理down和之后的同序列事件,一直往下(dispatchTouchEvent)问,都不处理,那么沿着来的路往回问(OnTouchEvent)。
down找到了谁来处理,那么其他事件就直接往下(dispatchTouchEvent),一直到目标,调用它的(OnTouchEvent),
特殊情况down的时候发现没有处理的view,那么其他事件流程走到顶级view:dector,直接返回false,接着交给activity处理。其他任何view都跟没有机会处理是否截断信号。
所以截断函数onInterceptTouchEvent, 一般的意义在于如何处理down信号。down信号最终到达哪里,其他信号才会下次直接一步一步走过去。
网上都是任务下派来作为比喻,很好。只不过大部分没有详细点明一些细节。自己详细比喻下。
假如某公司有多级部门。总公司中心处是activity。activity 总公司中心处 不记住任何东西。只派发任务,并处理大家都不处理的任务。而group会存储是否有我的分部门处理这件事。而分部分又会记载分分部分。直到分分分分分记录了某个人。
从总公司中心处,派发任务,当派发了某个任务,这里就比喻为点击了某处。那么就把这个任务给相关部门,此部门,一层一层的下放到最小的部门的某个人。 当然如果是好差事,中间会有截取。这里比喻的就是down事件的下发逻辑。
如果下放到某个人,或者被中间某人截取,但是他后来才发现他没有能力处理。那么就一层一层沿来路往上,看看谁能处理。这里就比喻 down下发时候的ontouchEvent都返回false的回归逻辑。最终有人处理,或者真的无人处理。
之后如果有这个任务的后续处理事件,就比喻为move,up事件。 那么还是从总公司中心处,一层一层过来(很多文章都是说交给某人处理,没有强调是从上往下一层一层的),直到交给处理这个任务的人,就不再往下了。
这里就是比喻其他事件,也是递归进去,并比较是否是当初存储的那个处理的view。是,就停止递归。
当然中间也可以再截取这个任务,然后再一层一层的通知原来处理这个事情的人,这个任务作废了。也就是比喻为中间截取了move或up信号,并一层一层发送cancel事件到down处理者。只发送一次cancel。以后截取的view就成为了新的处理者,截断所有事件。
如果当初是无人处理。那么后续事项,总公司中心处,还是需要先发给大部门,大部门知道无法处理。就直接说无法处理。总公司才自己处理。Activity是不存储谁处理事情的,只有group才存储。所以就算没有处理。activity还是要先问下顶级group。
当是down信号的时候,树型结构从顶往底,每层检查触摸事件点到了哪个子group或子view,目标是逐步精确的,刚开始是确定哪个group内,再后面某个group内的某个gruop,直到最准确的view。 详细就是 1.看看当前层是否截断,不截断的话,找到触摸点对应的子view或者子groupview。如此递进。 截断的话,不会去找触摸ivew,而直接进入当前view的dte的空参数函数。也就是调用消费流程2.2。 2.当递进到view,本质就是一个判断是否消费的流程,返回是否消费。 3.当递进到group无法再递进时,返回默认值false。上层得到false。 4.递进之后就是递归的归了。只有2种情况,有view消费,无view消费。返回值和mFirstTouchTarget都可以知道结果。 如果无view消费。说明更精确的下层居然不处理,那么范围精度更模糊的当前层需要看看自己是否处理,执行group基类(view)的dispatchtoucheven方法,其实就是view的方法。本质就是一个判断是否消费的流程。 如果有view消费。那么之后的流程会被跳过,因为已经消费过了。 小结:当处理down完信号的时候,每个group都有自己的mFirstTouchTarget,它们不是一样的,这个mFirstTouchTarget是一个逐步逼近目标view的过程,最后一层group的mFirstTouchTarget才是,比如按钮。 当然,当截断时,只会处理到截断那层。 另外没有处理的话,每层mFirstTouchTarget都是null,直接给activity处理。 当不是down信号的时候。树型结构从顶往底,每层看自己的变量mFirstTouchTarget是否存在。(因为性能关系吧,代码没有写出截断字段,但是firsttouche为空,就表明截断为true。操蛋) 1.如果存在,说明自己的子view或者子子view处理了down。找到子view,递归本函数。一直递归到最后一层的的view或group。view就直接消费流程,group的话,传递null了。又引发了2.2 2.如果不存在,(这个函数是最操蛋的,为了性能,阅读性基本为0.) 2.1说明没人处理,那么我处理看看,应该不会有这种情况,因为会有activity处理啊,如果真发生,那么也是无处理,因为第一层dector会处理,而且是默认的监听者都是null。所以应该是无处理。 2.2最常见是说明一个group在处理,最后一层的时候最后传递了null参数过来。那就执行group基类的的消费流程 2.3或者截断事件,因为没有去找触碰的子ivew。当然mFirstTouchTarget也是为null,不然,也不会进入这层,上层就返回了。截断就直接进入基类的消费流程。 ps.消费的流程:就是view 的dispath,其实就是 listenter+ oneventtouch.(on click) 当前层是否截断,就是函数 onInterceptTouchEvent 因为源代码没有可读性,代码是压缩版的,所以忘记了流程的话,先看这里的流程,再去找代码求证。
二。未完成的代码简化图。 因为代码是性能版。所以是一个fucking code!!!!!不是让人理解的版本。很弟弟的代码。
测试验证
需要验证的逻辑。
1.截断逻辑。
2.down处理逻辑。
3.非down处理逻辑。
4.无处理activity的最终处理的逻辑。
测试样例和期望
1.验证正常逻辑。正常的跑一次。期望down和up都递归到button
2.验证down的递和归逻辑。取消button的处理。验证处理逻辑,期望给activity处理。
3.验证截断不消费逻辑。内层截断,不消费情况下。 期望down事件的截断验证不会传递到button。up留在activity
4.验证截断消费逻辑。 内层截断,消费情况下期望down事件的截断验证不会传递到button。up也不到button.
5.验证非down逻辑。内层截断和不截断的情况下分别点击。 期望up截断到内层,不截到button。
6.按钮不消费,内层不截断,但有消费函数,期望达到截断一致效果。但是和1不同的是,up事件会传到button.
7.无意义的截断button的up。期望导致button无法触发点击事件。并且也不会给activity。
8,和7类似,但是换成接受内层,截断消费dowen,却主动放弃up。期望down不下放到button,up也不下方button,但是会触发上层的ontouchevent.
9.和7类似,但是截断move一次,预期,只截断一次,之后还是跟没有截断一样,不过自己也觉得太荒唐,但也不知道如何处理。
测试结果
1.符合期望,down和up都递归进入到button的dispatchTouchEvent函数
09-18 11:18:56.712 17501-17501/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:18:56.713 17501-17501/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 11:18:56.714 17501-17501/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:18:56.714 17501-17501/@: MyInnerLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 11:18:56.715 17501-17501/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:18:56.776 17501-17501/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 11:18:56.776 17501-17501/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 11:18:56.777 17501-17501/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 11:18:56.777 17501-17501/@: MyInnerLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 11:18:56.778 17501-17501/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 11:18:56.779 17501-17501/@: typical [onClick]. Line:46 : click button
2.修改button的click和LongClickable都为false。
符合预期,down 下发到Button的dispatchTouchEvent,又通过onTouchEvent回到Activity .最后up直接到Activity.不再下发了。
09-18 11:24:30.705 18199-18199/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.706 18199-18199/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.707 18199-18199/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.707 18199-18199/@: MyInnerLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.708 18199-18199/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.708 18199-18199/@: MyInnerLayout [onTouchEvent]. Line:34 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.709 18199-18199/@: MyOuterLayout [onTouchEvent]. Line:34 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.709 18199-18199/@: typical [onTouchEvent]. Line:74 : MotionEvent { action=ACTION_DOWN,
09-18 11:24:30.767 18199-18199/@: typical [onTouchEvent]. Line:74 : MotionEvent { action=ACTION_UP,
3.完全符合自己的期望。截断不消费和 button不消费一样。通过onTouchEvent回到Activity .最后up直接到Activity.不再下发了。
09-18 12:15:13.573 20201-20201/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.574 20201-20201/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.574 20201-20201/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.575 20201-20201/@: MyInnerLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.575 20201-20201/@: MyInnerLayout [onTouchEvent]. Line:43 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.576 20201-20201/@: MyOuterLayout [onTouchEvent]. Line:34 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.576 20201-20201/@: typical [onTouchEvent]. Line:75 : MotionEvent { action=ACTION_DOWN,
09-18 12:15:13.637 20201-20201/@: typical [onTouchEvent]. Line:75 : MotionEvent { action=ACTION_UP,
4.完全符合自己的期望。groupview截断消费就和一个button一样。所有事件递归到groupview,并由group消费。不再下发了。
09-18 12:27:46.992 21050-21050/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:27:46.993 21050-21050/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 12:27:46.993 21050-21050/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:27:46.994 21050-21050/@: MyInnerLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_DOWN,
09-18 12:27:46.994 21050-21050/@: MyInnerLayout [onTouchEvent]. Line:43 : MotionEvent { action=ACTION_DOWN,
09-18 12:27:47.054 21050-21050/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:27:47.055 21050-21050/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 12:27:47.056 21050-21050/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:27:47.056 21050-21050/@: MyInnerLayout [onTouchEvent]. Line:43 : MotionEvent { action=ACTION_UP,
5.上面例子已经验证up不会的button。不需要测试。
6.完全符合预期,反而有点失望,所以测试都符合预期。没有错误,反而怕有隐患。
下层不消费,上层不截断,但是消费。那么上层还是会被认为是此事项的消费view。
09-18 12:35:12.683 21394-21394/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.684 21394-21394/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.684 21394-21394/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.685 21394-21394/@: MyInnerLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.686 21394-21394/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.687 21394-21394/@: MyInnerLayout [onTouchEvent]. Line:35 : MotionEvent { action=ACTION_DOWN,
09-18 12:35:12.743 21394-21394/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:35:12.743 21394-21394/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 12:35:12.744 21394-21394/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:35:12.744 21394-21394/@: MyInnerLayout [onTouchEvent]. Line:35 : MotionEvent { action=ACTION_UP,
7.超出预期,出现了cancel事件。 确实没有触发点击。但是会发送一个cancel给button。呵呵。意外的收获。
09-18 12:51:02.620 22152-22152/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:51:02.621 22152-22152/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 12:51:02.621 22152-22152/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:51:02.622 22152-22152/@: MyInnerLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_DOWN,
09-18 12:51:02.622 22152-22152/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 12:51:02.668 22152-22152/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:51:02.668 22152-22152/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 12:51:02.669 22152-22152/@: MyInnerLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 12:51:02.670 22152-22152/@: MyInnerLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_UP,
09-18 12:51:02.671 22152-22152/@: MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_CANCEL,
8.这里和期望不一样。就是up事件不会像down事件一样逐层往上调用onTouchEvent,而是跳过上层group,直接给activity的onTouchEvent
09-18 17:27:25.137 27490-27490/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-18 17:27:25.138 27490-27490/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_DOWN,
09-18 17:27:25.138 27490-27490/@: MyInnerLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_DOWN,
09-18 17:27:25.139 27490-27490/@: MyInnerLayout [onInterceptTouchEvent]. Line:30 : MotionEvent { action=ACTION_DOWN,
09-18 17:27:25.139 27490-27490/@: MyInnerLayout [onTouchEvent]. Line:40 : MotionEvent { action=ACTION_DOWN,
09-18 17:27:25.216 27490-27490/@: MyOuterLayout [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_UP,
09-18 17:27:25.217 27490-27490/@: MyOuterLayout [onInterceptTouchEvent]. Line:27 : MotionEvent { action=ACTION_UP,
09-18 17:27:25.217 27490-27490/@: MyInnerLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_UP,
09-18 17:27:25.218 27490-27490/@: MyInnerLayout [onTouchEvent]. Line:40 : MotionEvent { action=ACTION_UP,
09-18 17:27:25.218 27490-27490/@: typical [onTouchEvent]. Line:80 : MotionEvent { action=ACTION_UP,
9.这里和期望不一样。只要截断一次,那么截断的view,就被当成了新的接收目标。第一次逐层发送cancel到原接受目标,之后cancel不会再发送了。恩,对,这个流程比较合理。还有一个要 注意的小细节,截断的信号不会给新截断者处理,还是给会原处理者,只不过是cancel。
09-19 10:40:13.814 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_DOWN,
09-19 10:40:13.815 21645-21645/ MyOuterLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_DOWN,
09-19 10:40:13.816 21645-21645/ MyInnerLayout [dispatchTouchEvent]. Line:22 : MotionEvent { action=ACTION_DOWN,
09-19 10:40:13.816 21645-21645/ MyInnerLayout [onInterceptTouchEvent]. Line:29 : MotionEvent { action=ACTION_DOWN,
09-19 10:40:13.817 21645-21645/ MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_DOWN,
09-19 10:40:14.025 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.026 21645-21645/ MyOuterLayout [onInterceptTouchEvent]. Line:28 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.027 21645-21645/ MyInnerLayout [dispatchTouchEvent]. Line:22 : MotionEvent { action=ACTION_CANCEL,
09-19 10:40:14.027 21645-21645/ MyInnerLayout [onInterceptTouchEvent]. Line:29 : MotionEvent { action=ACTION_CANCEL,
09-19 10:40:14.028 21645-21645/ MyButtonOk [dispatchTouchEvent]. Line:20 : MotionEvent { action=ACTION_CANCEL,
09-19 10:40:14.035 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.036 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.037 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.052 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.053 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.053 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.069 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.069 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.070 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.085 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.086 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.087 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.094 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.095 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.095 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_MOVE,
09-19 10:40:14.096 21645-21645/ MyOuterLayout [dispatchTouchEvent]. Line:21 : MotionEvent { action=ACTION_UP,
09-19 10:40:14.096 21645-21645/ MyOuterLayout [onTouchEvent]. Line:54 : MotionEvent { action=ACTION_UP,
09-19 10:40:14.097 21645-21645/ typical [onTouchEvent]. Line:79 : MotionEvent { action=ACTION_UP,
补充 activity ,window, dector的处理分析
C:\android\sdk\sources\android-28\android\app\activity.java /** * Called to process touch screen events. You can override this to * intercept all touch screen events before they are dispatched to the * window. Be sure to call this implementation for touch screen events * that should be handled normally. * * @param ev The touch screen event. * * @return boolean Return true if this event was consumed. */ public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) { return true; } else { return onTouchEvent(ev); } } private Window mWindow; public Window getWindow() { return mWindow; } mWindow = new PhoneWindow(this, window, activityConfigCallback); C:\android\sdk\sources\android-28\android\view\window.java /** * Used by custom windows, such as Dialog, to pass the touch screen event * further down the view hierarchy. Application developers should * not need to implement or call this. * */ public abstract boolean superDispatchTouchEvent(MotionEvent event); C:\android\sdk\sources\android-28\com\android\internal\policy\PhoneWindow.java @Override public boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event); } mDecor = (DecorView) preservedWindow.getDecorView(); mDecor = generateDecor(-1); DecorView就是Window的顶级View,它派生于FrameLayout,而FrameLayout又派生于groupview。所以我们可以最后追到ViewGroup.java 所以最终看ViewGroup.java的dispatchTouchEvent就可以。但是需要配合下面这幅图。其中contentViews是我们的布局xml文件的内容。
C:\android\sdk\sources\android-28\com\android\internal\policy\DecorView.java public boolean superDispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); }