android的Touch事件解析(dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent)

首先,這篇文章僅僅針對於由於觸摸(Touch)而觸發的事件。

Android的事件:onClick, onScroll, onFling等等,都是由許多個Touch組成的。其中Touch的第一個狀態肯定是ACTION_DOWN, 表示按下了屏幕。之後,touch將會有後續事件,可能是:

  • ACTION_MOVE //表示爲移動手勢

  • ACTION_UP //表示爲離開屏幕

  • ACTION_CANCEL //表示取消手勢,不會由用戶產生,而是由程序產生的

一個Action_DOWN, n個ACTION_MOVE, 1個ACTION_UP,就構成了Android中衆多的事件。

在Android中,有一類控件是中還可以包含其他的子控件,這類控件是繼承於ViewGroup類,例如:ListView, Gallery, GridView。

還有一類控件是不能再包含子控件,例如:TextView。

本文的主要討論對象就是ViewGroup類的控件嵌套時事件觸發情況。

對於ViewGroup類的控件,有一個很重要的方法,就是onInterceptTouchEvent(),用於處理事件並改變事件的傳遞方向,它的返回值是一個布爾值,決定了Touch事件是否要向它包含的子View繼續傳遞,這個方法是從父View向子View傳遞。

而方法onTouchEvent(),用於接收事件並處理,它的返回值也是一個布爾值,決定了事件及後續事件是否繼續向上傳遞,這個方法是從子View向父View傳遞。

touch事件在 onInterceptTouchEvent()和onTouchEvent以及各個childView間的傳遞機制完全取決於onInterceptTouchEvent()和onTouchEvent()的返回值。返回值爲true表示事件被正確接收和處理了,返回值爲false表示事件沒有被處理,將繼續傳遞下去。

ACTION_DOWN事件會傳到某個ViewGroup類的onInterceptTouchEvent,如果返回false,則DOWN事件繼續向子ViewGroup類的onInterceptTouchEvent傳遞,如果子View不是ViewGroup類的控件,則傳遞給它的onTouchEvent。

如果onInterceptTouchEvent返回了true,則DOWN事件傳遞給它的onTouchEvent,不再繼續傳遞,並且之後的後續事件也都傳遞給它的onTouchEvent。

如果某View的onTouchEvent返回了false,則DOWN事件繼續向其父ViewGroup類的onTouchEvent傳遞;如果返回了true,則後續事件會直接傳遞給其onTouchEvent繼續處理。(後續事件只會傳遞給對於必要事件ACTION_DOWN返回了true的onTouchEvent)

總結一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent則不一定。

 

轉自:http://www.cnblogs.com/kingcent/archive/2011/03/08/1977059.html

 

MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的傳遞順序

 onInterceptTouchEvent()用於處理事件並改變事件的傳遞方向。處理事件這個不用說了,你在函數內部編寫代碼處理就可以了。而決定傳遞方向的是返回值,返回爲false時事件會傳遞給子控件的onInterceptTouchEvent();返回值爲true時事件會傳遞給當前控件的onTouchEvent(),而不在傳遞給子控件,這就是所謂的Intercept(截斷)。

onTouchEvent() 用於處理事件,返回值決定當前控件是否消費(consume)了這個事件。可能你要問是否消費了又區別嗎,反正我已經針對事件編寫了處理代碼?答案是有區別!比如ACTION_MOVE或者ACTION_UP發生的前提是一定曾經發生了ACTION_DOWN,如果你沒有消費ACTION_DOWN,那麼系統會認爲ACTION_DOWN沒有發生過,所以ACTION_MOVE或者ACTION_UP就不能被捕獲。

本文源地址:http://www.cnblogs.com/rocky_yi/archive/2011/01/21/1941522.html# ,轉載請註明出處!

<?xml version="1.0" encoding="utf-8"?>
<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation
="vertical"
    android:layout_width
="fill_parent"
    android:layout_height
="fill_parent" >
    
<com.touchstudy.LayoutView2
        
android:orientation="vertical"
        android:layout_width
="fill_parent"
        android:layout_height
="fill_parent"
        android:gravity
="center">
       
<com.touchstudy.MyTextView 
            
android:layout_width="wrap_content"
            android:layout_height
="wrap_content"
            android:id
="@+id/tv"
            android:text
="AB"
            android:textSize
="40sp"
            android:textStyle
="bold"
            android:background
="#FFFFFF"
            android:textColor
="#0000FF"/>
   
</com.touchstudy.LayoutView2>
</com.touchstudy.LayoutView1>

 

 

在沒有重寫onInterceptTouchEvent()和onTouchEvent()的情況下(他們的返回值都是false), 對上面這個佈局,MotionEvent事件的傳遞順序如下:

 

當某個控件的onInterceptTouchEvent()返回值爲true時,就會發生截斷,事件被傳到當前控件的onTouchEvent()。如我們將LayoutView2的onInterceptTouchEvent()返回值爲true,則傳遞流程變成:

 

 如果我們同時將LayoutView2的onInterceptTouchEvent()和onTouchEvent()設置成true,那麼LayoutView2將消費被傳遞的事件,同時後續事件(如跟着ACTION_DOWN的ACTION_MOVE或者ACTION_UP)會直接傳給LayoutView2的onTouchEvent(),不傳給其他任何控件的任何函數。同時傳遞給子空間一個ACTION_CANCEL事件。傳遞流程變成(圖中沒有畫出ACTION_CANCEL事件):

          

附SDK給出的說明:

·  You will receive the down event here.
·  The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
·  For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
·  If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.


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 方法進行分發,

1、如果dispatchTouchEvent返回true,則交給這個view的onTouchEvent處理,    如果最終需要處理事件的viewonTouchEvent()返回了false,那麼該事件將被傳遞至其上一層次的viewonTouchEvent()處理。如果最終需要處理事件的view onTouchEvent()返回了true,那麼後續事件將可以繼續傳遞給該viewonTouchEvent()處理。

2、如果dispatchTouchEvent返回 false ,則交給這個view的interceptTouchEvent方法來決定是否

要攔截這個事件,如果 interceptTouchEvent 返回 true,也就是

3、若果interceptTouchEvent返回true,表示攔截掉了,則交給它的onTouchEvent 來處理,

4、如果 interceptTouchEvent 返回 false,那麼就傳遞給子view ,由子 view 的 d

ispatchTouchEvent 再來開始這個事件的分發。

5、如果事件傳遞到某一層的子 view 的onTouchEvent上了,這個方法返回了 false ,那麼這個事件

會從這個view 往上傳遞,都是 onTouchEvent來接收。

6、如果傳遞到最上面的 onTouchEvent 也返回 false的話,這個事件就會“消失”,而且接收

不到下一次事件。

 
發佈了25 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章