题目如下:View事件传递;事件是从哪里到达Activity的?ViewRootImpl的作用?有A、B两个Button,各自设置了OnClickListener,在A上按下,移动到B上抬起,会触发OnClickListener么?为何?UP事件谁接收到了?OnClickListener触发的条件是哪些?
1.1 View事件传递;事件是从哪里到达Activity的?
这个以后专门写一篇文章单独分析事件如何从屏幕点击最终到达Activity的。
1.2 基本三大作用:
作为WindowManager和DecorView的纽带,桥梁。
完成View的绘制过程,包括measure,layout,draw过程。
向DecorView分发收到的用户发起的Event事件,比如按键、触屏事件等。
1.3 我们先用代码验证,然后再结合源码来分析
按照在A按钮按下,然后一直移动 直到B按钮位置才抬起来 结果是:
刚按下时候触发A按钮的 ACTION_DOWN,然后在A范围内移动,触发ACTION_MOVE,当不在A范围内移动时,没有事件触发,然后又移动到A范围内,依然ACTION_MOVE。最后再移动到B按钮上抬起,触发A按钮的ACTION_UP。过程中没有触发B按钮任何事件。
不会触发OnClickListener
1.4 UP事件被A按钮收到了。
1.5 源码来分析:
首先看不会触发OnClickListener原因。
而Onclick事件是在UP事件中触发
可以看到逻辑也比较简单:当触发ACTION_UP事件时,也就是手指抬起时,当View处于Pressed状态。就会触发performClickInternal()。这里面也会调用performClick。也就是回调onClick。
所以结论:当A按钮移出View后再B后抬起是不会触发onClick事件的。
UP事件没有被B按钮处理是B都没有处理ACTION_DOWN事件(这是一个事件序列的开端)。显然是不会触发UP事件的。
1.6 OnClickListener触发的条件是哪些?
先给出结论
设置了setOnClicklistener
View没有重写OnTouchEvent(默认情况下 这个方法返回值是clickable,也就是说View如果是可点击的,那么就会消耗事件)
手指没有移动出View的范围
有抬起动作。
现在主要分析下如果View重写OnTouchEvent的情况。为什么就不会触发了OnClick事件了。
当我重写onTouchEvent 无论之间返回false或者ture时,都不会触发了onClick事件
此时的日志始终没有打印。其实想想也是我们的onClick回调是在View#onTouchEvent的ACTION_UP那一段代码触发的。我们点击按钮时候都没触发View的onTouchEvent方法怎么会进行onClick回调呢。
当自定义View时候重写了onTouchEvent方法后,还想要响应onClick回调时,可以在ACTION_UP里面手动调用
return true;
当返回return super.onTouchEvent(event);
现象:onClick 会触发两次
当返回return false; 不会触发,即使调用了performClick(); 因为return false代表View不处理此事件了。
网友评论