Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android Touch事件原理加實例分析

Android Touch事件原理加實例分析

編輯:關於android開發

       Android中有各種各樣的事件,以響應用戶的操作。這些事件可以分為按鍵事件和觸屏事件。而Touch事件是觸屏事件的基礎事件,在進行Android開發時經常會用到,所以非常有必要深入理解它的原理機制。

       Android Touch事件原理描述

       一個最簡單的屏幕觸摸動作觸發了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP。

       當屏幕中包含一個ViewGroup,而這個ViewGroup又包含一個子view,這個時候android系統如何處理Touch事件呢?到底是ViewGroup來處理Touch事件,還是子view來處理Touch事件呢?我只能很肯定的對你說不一定。呵呵,為什麼呢?看看下面我的調查結果你就明白了。

       Android系統中的每個View的子類都具有下面三個和TouchEvent處理密切相關的方法:

       1)public boolean dispatchTouchEvent(MotionEvent ev)  這個方法用來分發TouchEvent

       2)public boolean onInterceptTouchEvent(MotionEvent ev) 這個方法用來攔截TouchEvent

       3)public boolean onTouchEvent(MotionEvent ev) 這個方法用來處理TouchEvent

       當TouchEvent發生時,首先Activity將TouchEvent傳遞給最頂層的View, TouchEvent最先到達最頂層 view 的 dispatchTouchEvent ,然後由  dispatchTouchEvent 方法進行分發,如果dispatchTouchEvent返回true ,則交給這個view的onTouchEvent處理,如果dispatchTouchEvent返回 false ,則交給這個 view 的 interceptTouchEvent 方法來決定是否要攔截這個事件,如果 interceptTouchEvent 返回 true ,也就是攔截掉了,則交給它的 onTouchEvent 來處理,如果 interceptTouchEvent 返回 false ,那麼就傳遞給子 view ,由子 view 的 dispatchTouchEvent 再來開始這個事件的分發。如果事件傳遞到某一層的子 view 的 onTouchEvent 上了,這個方法返回了 false ,那麼這個事件會從這個 view 往上傳遞,都是 onTouchEvent 來接收。而如果傳遞到最上面的 onTouchEvent 也返回 false 的話,這個事件就會“消失”,而且接收不到下一次事件。

       Android Touch事件實例分析

       通過語言描述這個處理邏輯很抽象,下面我就用代碼來具體說明一下。

       layout配置文件 main.xml:

XML/HTML代碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <test.lzqdiy.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:gravity="center" >  
  7.        <test.lzqdiy.MyTextView    
  8.             android:layout_width="200px"  
  9.             android:layout_height="200px"  
  10.             android:id="@+id/tv"  
  11.             android:text="lzqdiy"  
  12.             android:textSize="40sp"  
  13.             android:textStyle="bold"  
  14.             android:background="#FFFFFF"  
  15.             android:textColor="#0000FF"/>  
  16. </test.lzqdiy.MyLinearLayout>  

       節點層次很簡單,一個LinearLayout中添加了一個TextView。

       下面是java代碼:

Java代碼
  1. package test.lzqdiy;   
  2.   
  3. import android.app.Activity;   
  4. import android.os.Bundle;   
  5.   
  6. public class TestTouchEventApp extends Activity {   
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {   
  10.         super.onCreate(savedInstanceState);   
  11.         setContentView(R.layout.main);   
  12.     }   
  13. }   
  14. package test.lzqdiy;   
  15.   
  16. import android.content.Context;   
  17. import android.util.AttributeSet;   
  18. import android.util.Log;   
  19. import android.view.MotionEvent;   
  20. import android.widget.LinearLayout;   
  21.   
  22. public class MyLinearLayout extends LinearLayout {   
  23.     private final String TAG = "MyLinearLayout";   
  24.   
  25.     public MyLinearLayout(Context context, AttributeSet attrs) {     
  26.         super(context, attrs);     
  27.         Log.d(TAG, TAG);     
  28.     }   
  29.   
  30.     @Override  
  31.     public boolean dispatchTouchEvent(MotionEvent ev) {   
  32.         int action = ev.getAction();  
  33.    
  34.         switch (action) {     
  35.         case MotionEvent.ACTION_DOWN:     
  36.             Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN"); 
  37.             break;     
  38.         case MotionEvent.ACTION_MOVE:     
  39.             Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE"); 
  40.             break;     
  41.         case MotionEvent.ACTION_UP:     
  42.             Log.d(TAG, "dispatchTouchEvent action:ACTION_UP"); 
  43.             break;     
  44.         case MotionEvent.ACTION_CANCEL:     
  45.             Log.d(TAG, "dispatchTouchEvent action:ACTION_CANCEL"); 
  46.             break;     
  47.         }   
  48.  
  49.         return super.dispatchTouchEvent(ev);   
  50.     }   
  51.   
  52.     @Override  
  53.     public boolean onInterceptTouchEvent(MotionEvent ev) {     
  54.         int action = ev.getAction();  
  55.    
  56.         switch (action) {     
  57.         case MotionEvent.ACTION_DOWN:     
  58.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_DOWN"); 
  59.             break;     
  60.         case MotionEvent.ACTION_MOVE:     
  61.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_MOVE"); 
  62.             break;     
  63.         case MotionEvent.ACTION_UP:     
  64.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_UP"); 
  65.             break;     
  66.         case MotionEvent.ACTION_CANCEL:     
  67.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_CANCEL"); 
  68.             break;     
  69.         }     
  70.         return false;     
  71.     }   
  72.   
  73.     @Override  
  74.     public boolean onTouchEvent(MotionEvent ev) {     
  75.         int action = ev.getAction();   
  76.   
  77.         switch (action) {     
  78.         case MotionEvent.ACTION_DOWN:     
  79.             Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");     
  80.             break;     
  81.         case MotionEvent.ACTION_MOVE:     
  82.             Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");     
  83.             break;     
  84.         case MotionEvent.ACTION_UP:     
  85.             Log.d(TAG, "---onTouchEvent action:ACTION_UP");     
  86.             break;     
  87.         case MotionEvent.ACTION_CANCEL:     
  88.             Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");   
  89.             break;     
  90.         }   
  91.   
  92.         return true;   
  93.     }   
  94.   
  95. }   
  96.   
  97. package test.lzqdiy;   
  98.   
  99. import android.content.Context;   
  100. import android.util.AttributeSet;   
  101. import android.util.Log;   
  102. import android.view.MotionEvent;   
  103. import android.widget.TextView;   
  104.   
  105. public class MyTextView extends TextView {   
  106.   
  107.     private final String TAG = "MyTextView";   
  108.   
  109.     public MyTextView(Context context, AttributeSet attrs) {     
  110.         super(context, attrs);     
  111.     }   
  112.   
  113.     @Override  
  114.     public boolean dispatchTouchEvent(MotionEvent ev) {   
  115.         int action = ev.getAction();   
  116.   
  117.         switch (action) {     
  118.         case MotionEvent.ACTION_DOWN:     
  119.             Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN"); 
  120.             break;     
  121.         case MotionEvent.ACTION_MOVE:     
  122.             Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE"); 
  123.             break;     
  124.         case MotionEvent.ACTION_UP:     
  125.             Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");     
  126.             break;     
  127.         case MotionEvent.ACTION_CANCEL:     
  128.             Log.d(TAG, "onTouchEvent action:ACTION_CANCEL");     
  129.             break;     
  130.         } 
  131.   
  132.         return super.dispatchTouchEvent(ev);   
  133.     }   
  134.   
  135.     @Override  
  136.     public boolean onTouchEvent(MotionEvent ev) {     
  137.         int action = ev.getAction();   
  138.   
  139.         switch (action) {     
  140.         case MotionEvent.ACTION_DOWN:     
  141.             Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");     
  142.             break;     
  143.         case MotionEvent.ACTION_MOVE:     
  144.             Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");     
  145.             break;     
  146.         case MotionEvent.ACTION_UP:     
  147.             Log.d(TAG, "---onTouchEvent action:ACTION_UP");     
  148.             break;     
  149.         case MotionEvent.ACTION_CANCEL:     
  150.             Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");     
  151.             break;     
  152.         }   
  153.   
  154.         return true;     
  155.     }     
  156. }  

       為了指代方便,下面將MyLinearLayout簡稱為L,將MyTextView簡稱為T,L.onInterceptTouchEvent=true 表示的含義為MyLinearLayout中的onInterceptTouchEvent方法返回值為true,通過程序運行時輸出的Log來說明調用時序。

       第1種情況 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=true 輸出下面的Log:

D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(11865): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_MOVE
D/MyTextView(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyTextView(11865): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_UP
D/MyTextView(11865): dispatchTouchEvent action:ACTION_UP
D/MyTextView(11865): ---onTouchEvent action:ACTION_UP

       結論:TouchEvent完全由TextView處理。

       第2種情況  L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=false 輸出下面的Log:

D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_UP

       結論:TextView只處理了ACTION_DOWN事件,LinearLayout處理了所有的TouchEvent。

       第3種情況  L.onInterceptTouchEvent=true&& L.onTouchEvent=true 輸出下面的Log:

D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_UP

       結論:LinearLayout處理了所有的TouchEvent。

       第4種情況  L.onInterceptTouchEvent=true&& L.onTouchEvent=false 輸出下面的Log:

D/MyLinearLayout(13452): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): ---onTouchEvent action:ACTION_DOWN

       結論:LinearLayout只處理了ACTION_DOWN事件,那麼其他的TouchEvent被誰處理了呢?答案是LinearLayout最外層的Activity處理了TouchEvent。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved