類似文章: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()。