Android Touch事件

jopen 10年前發布 | 11K 次閱讀 Android開發 移動開發 Android Touch

Android中跟Touch事件有關的事件有三個:
    public boolean dispatchTouchEvent(MotionEvent ev):傳遞Touch事件至target view(可以是自己)。
    public boolean onInterceptTouchEvent(MotionEvent ev):在ViewGroup中定義,用于攔截Touch事件的傳遞。
    public boolean onTouchEvent(MotionEvent event): Touch事件處理函數。

 

  先說下事件傳遞的兩種方式:
    隧道方式:從根元素依次往下傳遞直到最內層子元素或在中間某一元素中由于某一條件停止傳遞。 
    冒泡方式:從最內層子元素依次往外傳遞直到根元素或在中間某一元素中由于某一條件停止傳遞。

 

  Touch事件通過dispatchTouchEvent以隧道方式從上往下傳遞。如果在一個View中執行onTouchEvent時返回 true的話,接下來的事件(ACTION_DOWN后的ACTION_UP,及可能在中間包含的若干個ACTION_MOVE,從 ACTION_DOWN至ACTION_UP為一個連續事件,這是自己想的,不知道準確否)仍會傳遞到這個View的onTouchEvent,如果返回 false的話,接下來的事件就不會再傳遞到這個View,而是執行其Parent View的onTouchEvent,每當一個View的onTouchEvent事件返回false,接下來的事件(如果還有的話)就會止步于這個 View的Parent View,每次上升一個層次,類似于冒泡方式。

 

  Touch事件傳遞過程中經過的元素都是一個View,但是事件處理的最外層的元素卻不是View,除下跟Window有關的事件,當一個 Touch事件發生的時候,會首先調用當前Activity的dispatchTouchEvent函數,然后才將事件傳遞至下層的View元素。當 dispatchTouchEvent經過一個View往下傳遞的時候,如果這個View是一個ViewGroup,會調用其 onInterceptTouchEvent函數,這個函數表示是否攔截Touch事件,如果這個函數返回true,表示這個ViewGroup攔截了事件的傳遞,Touch事件不會再往下傳遞給它的子View,而是由它處理,所以會調用它的onTouchEvent函數,如果在傳遞的過程中沒有 ViewGroup攔截事件,即經過的所有ViewGroup都返回false,那么事件最終會傳遞至最內層的View,一般是一個Widget,當然也可以是一ViewGroup(其內部不包含任何元素),如果最后事件傳遞到一View(非ViewGroup),那么會首先調用這個View的 onTouchListener(如果設置了的話),如果onTouchListener返回false則繼續調用View的 onTouchEvent(默認返回true),如果最后事件傳遞到一ViewGroup(無子View),會調用它的onTouchEvent函數,默認返回false。


  如果調用一個View的onTouchEvent函數時返回true的話,那么接下來的Touch Event事件(ACTION_DOWN后的ACTION_UP,及可能在中間包含的若干個ACTION_MOVE,從ACTION_DOWN至 ACTION_UP為一個連續事件,這是自己想的,不知道準確否)仍會傳遞到這個View并調用它的onTouchEvent函數,在 onTouchEvent函數中可以根據條件返回不同的值,如果某一次在此函數中返回了false那么接下來的Touch Event事件就不會再傳遞到這個View,而會在其Parent View終止,調用其Parent View的onTouchEvent。如果所有的View都的onTouchEvent函數都返回false,那么接下來的Touch Event事件會由Activity處理,即調用Activity的onTouchEvent函數。

 

  當調用ViewGroup的dispatchTouchEvent函數時,會首先調用onInterceptTouchEvent函數判斷有沒有攔截事件,如果沒有攔截(返回false),則會依次調用這個ViewGroup的所有子View的dispatchTouchEvent函數。比如一個FrameLayout上層疊了三個ViewGroup,那么在這個FrameLayout的dispatchTouchEvent中會依次調用這三個 ViewGroup的dispatchTouchEvent函數,而在這三個ViewGroup的dispatchTouchEvent中也會依次調用他們的子View的dispatchTouchEvent函數,直到其中一個View的dispatchTouchEvent返回true,表示已經處理了這個Touch事件,不需要再調用這個View的Slibling Views。比如調用這三個層疊的ViewGroup的dispatchTouchEvent函數時,如果第一個ViewGroup的 dispatchTouchEvent函數就返回了true(已經消耗掉了這個事件),那么其他兩個ViewGroup的 dispatchTouchEvent就不會再被調用。可以自定義一個ViewGroup的子類并重載他的dispatchTouchEvent函數,使其處理過Touch事件后仍返回false,那么就還會調用其他兄弟View的dispatchTouchEvent函數。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!