类似文章:android
------app
1, 界面布局 Linear Layout 包裹一个TextView。textView 上设置了按压效果。函数
问:当手指从TextView 上按下,而后移动手指到TextView 边界之外,发生那些事件?源码分析
布局文件以下:布局
<test.lee.carlyle.com.myapplication.touch.MyLinear xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal" android:id="@+id/linear" > <test.lee.carlyle.com.myapplication.touch.MYTextView android:layout_width="80dp" android:layout_height="50dp" android:background="@drawable/bg_sl" android:layout_margin="10dp" android:text="GOOD 0" /> <test.lee.carlyle.com.myapplication.touch.MYTextView android:layout_width="40dp" android:layout_height="30dp" android:background="@drawable/bg_sl" android:layout_margin="10dp" android:text="GOOD 1" /> </test.lee.carlyle.com.myapplication.touch.MyLinear>
你觉得 界面上的效果是这样???:《按压时 TextView 变色。 拖拽过程当中,当手指离开textView 后,颜色恢复到normal 状态。》spa
可是你忽略掉了一点:当没有给TextView 设置事件的时候事件流程状态。日志
2,事件执行流程:code
10-28 17:07:25.957 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action down text View 0 action down 10-28 17:07:25.963 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action move text View 0 action move 10-28 17:07:26.260 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action move text View 0 action move 10-28 17:07:26.276 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action move 10-28 17:07:26.277 20796-20796/test.lee.carlyle.com.myapplication E/motion: text View 0 action move 10-28 17:07:26.292 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action move text View 0 action move 10-28 17:07:26.293 20796-20796/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch action up 10-28 17:07:26.294 20796-20796/test.lee.carlyle.com.myapplication E/motion: text View 0 action up
中间省略了一堆move 日志。 能够看到在手指移出TextView 的范围以后,仍然还将move 事件继续分发到当前touch 焦点的试图上。可是在手指移出textView 视图的时候,按压效果消失了。orm
以前一直觉得这个drawable state change 是由于parent 发出了 state cacel 事件致使的。并觉得事件将再也不传入。由于以为合理就没有深究。。。xml
那么,既然不是 cancel 事件,那么这个 drawable state pressed 状态是怎么消失的呢?
看代码:
原来是View 本身在move 的时候本身处理的。
3, 问题扩展:
可见:触摸事件流程是会在视图树中,的确会肯定一个处理事件的View路径的。在上层onTouch处理后,是不会再分发给下层的dispatch 去尝试处理的。
<LinearLayout dispatchTouchDown= true; onTouchDown= true> <LinearLayout dispatchTouchDown= false; onTouchDown= false> <TextView/> </LinearLayout> </LinearLayout> 日志以下: 10-28 17:48:40.376 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action down MyLinear dispatch 2131165251 action down text View 0 action down 10-28 17:48:40.378 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear onTouch -1 action down 10-28 17:48:40.388 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action move MyLinear onTouch -1 action move 10-28 17:48:40.434 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action move MyLinear onTouch -1 action move 10-28 17:48:40.450 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action move MyLinear onTouch -1 action move 10-28 17:48:41.112 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action move MyLinear onTouch -1 action move 10-28 17:48:41.128 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action move 10-28 17:48:41.129 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear onTouch -1 action move 10-28 17:48:41.130 22150-22150/test.lee.carlyle.com.myapplication E/motion: MyLinear dispatch-1 action up MyLinear onTouch -1 action up
实验以下:
<LinearLayout dispatchTouchDown= true; onTouchDown= true> <LinearLayout dispatchTouchDown= true; dispatchTouchMove = false; onTouchDown= false> <TextView onCLickListenter = true /> </LinearLayout> </LinearLayout>
日志显示,事件都将由TextView 进行处理。外层一致dispatch 到当前层的TextView 上。而后而后交由TextView 来处理。
疑问: 如该在TextView 中,onTouchEvent down 返回true, 其余的返回false , 又会如何呢?
实验以下:
<LinearLayout dispatchTouchDown= true; onTouchDown= true> <LinearLayout dispatchTouch= true; onTouchDown= false> <TextView onCLickListenter = true ; onTouchDown= true ; onTouchMove = false /> </LinearLayout> </LinearLayout>
实验结果:TextView 的OnTouchEvent 在actionDown 以外返回false。并不影响事件传递流程。
结论:只有actionDown 事件中返回true 或 fase 会影响视图树的事件传递流程。
3、源码分析:
事件传递树是如何构成的?在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()。