一、案例
界面布局 Linear Layout 包裹一个TextView。textView 上设置了按压效果。
问:当手指从TextView 上按下,然后移动手指到TextView 边界以外,发生那些事件?
布局文件如下:
你以为 界面上的效果是这样???:《按压时 TextView 变色。 拖拽过程中,当手指离开textView 后,颜色恢复到normal 状态。》
但是你忽略掉了一点:当没有给TextView 设置事件的时候事件流程状态。
当TextView 没有点击事件的时候,OnTouchEvent down 返回false 。 之后不再相应按压事件。也没有按压效果。
当在TextView 上设置了点击事件后,有了按压效果。
二、事件执行流程:
中间省略了一堆move 日志。 可以看到在手指移出TextView 的范围之后,仍然还将move 事件继续分发到当前touch 焦点的试图上。但是在手指移出textView 视图的时候,按压效果消失了。
之前一直以为这个drawable state change 是因为parent 发出了 state cacel 事件导致的。并以为事件将不再传入。因为觉得合理就没有深究。。。
那么,既然不是 cancel 事件,那么这个 drawable state pressed 状态是怎么消失的呢?
看代码:
原来是View 自己在move 的时候自己处理的。
三、 问题扩展:
当在父布局中 dispatchTouchEvent 的时候,直接返回false 会怎样?为了验证这个问题,我将布局层级修改了一下,在当前布局的外层,再增加了一层LinearLayout。
在dispatch TouchEvent ActionDown 的时候直接返回false: 事件将不会继续从这层的LinearLayout 继续分发。但是 ActionDown事件却一次传递到TextView 上了。导致TextView press state change。但是无法恢复了。由于当前ViewGroup 层不分发事件,因此,事件在当前层的上层,直接交给OnTouchEvent 进行处理。
如果上层(TextView -> parent -> parent)的ViewGroup 的OnTouchEvent down 事件返回了ture : 后续事件将保持这个流程一直传递下来。
如果上层的ViewGroup 的OnTouchEvent down 事件返回了false:事件将继续交给上层的上层的onTouchEvent来判断。
可见:触摸事件流程是会在视图数中,的确会确定一个处理事件的View路径的。在上层onTouch处理后,是不会再分发给下层的dispatch 去尝试处理的。
在dispatch TouchEvent 非ActionDown 的时候返回false:此时不影响分发流程。
实验如下:
日志显示,事件都将有TextView 进行处理。外层一致dispatch 到当前层的TextView 上。然后然后交由TextView 来处理。
疑问: 如该在TextView 中,onTouchEvent down 返回true, 其他的返回false , 又会如何呢?
实验如下:
实验结果:TextView 的OnTouchEvent 在actionDown 之外返回false。并不影响事件传递流程。
四、源码分析:
事件传递树是如何构成的?在ViewGroup 中有一个属性。这是一个链式结构。
private TouchTarget mFirstTouchTarget;
确定View tree 事件传递链接的代码在这里:
这个函数在 ViewGroup的dispatchTouchEvent 中的 ActionDown 事件中执行。在此时将确定本层的TouchTarget链表。
其中关键方法:dispatchTransformedTouchEvent. 这个方法确定了是向下层分发(child.dispatch)还是向同层分发(super.dispatch:View.dispatchTouchEvent())。
可见在View.dispatchTouchEvent 中,调用了View.OnTouchEvent.而View.onTouchEvent 的返回值只有在ActionDown 事件时,才能通过是否View 作为TouchTarget 添加到TouchTarget list 中的方式影响到事件分发流程。
一路向上:我们来到Activity dispatchTouchEvent 的代码中看看
跟踪代码发现。getWindow().superDispatchTouchEvent() 实际的处理者是 PhoneWidnow 中的DecoreView(即ViewGroup).dispatchTouchEvent()。
网友评论