Android觸摸事件傳遞

前言:本篇博文主要分析關(guān)于onTouchEvent,dispatchTouchEvent和onInterceptTouchEvent這三個方法的作用和它們之間的關(guān)系,通過流程圖來解釋觸摸事件(MotionEvent)是怎么在三個方法中傳遞的漩怎;

為了了解三個方法之間的關(guān)系,我們通過一個demo來分析它們之間的關(guān)系,demo主要內(nèi)容為在一個activity上設置兩個布局控件,一個為LinearLayout左医,一個是TextView,兩個控件都自定義重寫了它們的onTouchEvent同木、dispatchTouchEvent和onInterceptTouchEvent方法浮梢,并用logcat打印出各個方法相應的log標記,通過觸摸控件后log的打印順序就可知道他們的調(diào)用順序了彤路,通過調(diào)用順序去分析事件的傳遞流程秕硝,如下圖所示為activity的視圖


其中紅色區(qū)域為Textview的視圖,底下綠色區(qū)域為LinearLayout的視圖洲尊,最底下藍色區(qū)域為activity的視圖远豺;下面貼上代碼:

public class GestureDemo extends Activity {  

    public final static String TAG = "GestureDemo";  
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);   
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
          
        Log.i(TAG,"Activity onTouchEvent. action="+getAction(event));  
        return super.onTouchEvent(event);  
    }  
      
    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
          
        Log.i(TAG,"Activity dispatchTouchEvent. action="+getAction(ev));  
        return super.dispatchTouchEvent(ev);  
    }   
}  
public class MyLinearLayout extends LinearLayout {  
  
    public MyLinearLayout(Context context) {  
        super(context);  
    }  
      
    public MyLinearLayout(Context context, AttributeSet attrs) {  
        this(context, attrs, 0);  
    }  
      
    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {  
        super(context,attrs,defStyleAttr);  
    }  
      
    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
  
        Log.i(GestureDemo.TAG,"MyLinearLayout dispatchTouchEvent. action="+GestureDemo.getAction(ev));  
        return super.dispatchTouchEvent(ev);  
    }  
      
    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        Log.i(GestureDemo.TAG,"MyLinearLayout onInterceptTouchEvent. action="+GestureDemo.getAction(ev));  
        return super.onInterceptTouchEvent(ev);  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        Log.i(GestureDemo.TAG,"MyLinearLayout onTouchEvent. action="+GestureDemo.getAction(event));  
        return super.onTouchEvent(event);  
    }  
}
public class MyTextView extends TextView {  
  
    public MyTextView(Context context) {  
        super(context);  
    }  
  
    public MyTextView(Context context, AttributeSet attrs){  
        super(context,attrs);  
    }  
      
    MyTextView(Context context, AttributeSet attrs, int defStyleAttr){  
        super(context,attrs,defStyleAttr);  
    }  
      
    @Override  
    public boolean dispatchTouchEvent(MotionEvent event) {  
        Log.i(GestureDemo.TAG,"MyTextView dispatchTouchEvent. action="+GestureDemo.getAction(event));  
        return super.dispatchTouchEvent(event);  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        Log.i(GestureDemo.TAG,"MyTextView onTouchEvent. action="+GestureDemo.getAction(event));  
        return super.onTouchEvent(event);  
    }  
} 

注: 每一次屏幕觸摸后的手勢事件都是連續(xù)地由一個down事件、若干move事件和一個up事件組成坞嘀,每次都必須是down事件先發(fā)生躯护,最后一個是up事件;

  • 觸摸事件:每一個down事件姆吭、move事件或up事件都為一個獨立的觸摸事件榛做;
  • 手勢事件:由一系列連續(xù)的觸摸事件組成的一個完整的手勢唁盏,比如單擊手勢事件為down-up, 滑動事件為down-move…move-up内狸;

下面通過逐個改變各個方法的返回值,分析它們之間的傳遞圖厘擂;

一昆淡、 關(guān)于onTouchEvent事件

1. 所有方法都返回父類的方法,即MotionEvent沒有被子控件消耗掉刽严,最終只有在activity的onTouchEvent消失掉(系統(tǒng)默認傳遞流程)昂灵;
2. Activity的onTouchEvent方法返回true避凝,其事件傳遞流程和上一個相同
3. MyLinearLayout的onTouchEvent返回true
4. MyTextView的onTouchEvent返回true;

總結(jié):以上四張圖中眨补,只改動onTouchEvent的返回值管削,其他方法都調(diào)用父類方法,也就是傳遞流程都為系統(tǒng)默認的流程撑螺,沒有人為干預含思,圖1即是默認的系統(tǒng)流程,而圖2,3,4通過改變onTouchEvent的返回值為true來終止事件的繼續(xù)傳遞甘晤;從圖中可知含潘,當屏幕觸摸發(fā)生時,down事件每次都是由系統(tǒng)先調(diào)用最底層的activity的dispatchTouchEvent事件线婚,然后繼續(xù)往上傳遞到最頂層控件遏弱,然后由onTouchEvent往下傳遞,按照默認傳遞順序塞弊,如果哪個控件返回true漱逸,事件就在那個控件停止,即被這個控件消耗掉居砖,如:activity和MyLinearLayout的onTouchEvent都返回true虹脯,那么事件只傳遞到MyLinearLayout的onTouchEvent,因為事件先經(jīng)過MyLinearLayout的onTouchEvent奏候,先被它截住了循集;而后續(xù)的move、up事件則會根據(jù)上個down事件最終在哪個控件被消耗掉蔗草,然后按照默認系統(tǒng)流程傳遞到該控件的dispatchTouchEvent后直接傳遞給自己的onTouchEvent咒彤,不會再往上層控件傳遞;

二咒精、關(guān)于dispatchTouchEvent

1. MyLinearLayout的dispatchTouchEvent返回true
2. MyTextView的dispatchTouchEvent返回true
3. MyLinearLayout的dispatchTouchEvent返回false
4. MyTextView的dispatchTouchEvent返回false

總結(jié):dispatchTouchEvent從方法名大約就可以知道其功能是分發(fā)觸摸事件镶柱,該方法會根據(jù)它的返回值來決定事件要往哪個方向傳遞:

(1)若返回父類方法,則交由系統(tǒng)來決定模叙,即為系統(tǒng)默認方向繼續(xù)傳遞給上層控件的方法歇拆;
(2)若返回true,則不再繼續(xù)傳遞范咨,傳遞到這個方法為止故觅,即這個方法消耗了事件;
(3)若返回false渠啊,事件傳遞到該方法后输吏,事件退回到底下的父控件,繼續(xù)往系統(tǒng)默認方向傳遞替蛉;如圖8所示贯溅,MyTextView的dispatchTouchEvent返回false拄氯,事件退回到MyLinearLayout的onInterceptTouchEvent,繼續(xù)往MyLinearLayout的onTouchEvent傳遞它浅,即相當于以MyLinearLayout為最頂層控件译柏;

三、關(guān)于onInterceptTouchEvent

1. MyLinearLayout的onInterceptTouchEvent返回true

總結(jié):該方法只有ViewGroup的控件才會有姐霍,其父類的方法直接返回false艇纺,所以返回false就為圖1中按默認方向傳遞了;該方法的作用就是攔截觸摸事件邮弹,如果返回true黔衡,就是在當前控件攔截住觸摸事件,傳遞給自己的onTouchEvent方法腌乡,再繼續(xù)往底下控件傳遞給onTouchEvent盟劫,如果返回false或父類方法,就傳遞給它上面控件的dispatchTouchEvent与纽;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侣签,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子急迂,更是在濱河造成了極大的恐慌影所,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件僚碎,死亡現(xiàn)場離奇詭異猴娩,居然都是意外死亡,警方通過查閱死者的電腦和手機勺阐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門卷中,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渊抽,你說我怎么就攤上這事蟆豫。” “怎么了懒闷?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵十减,是天一觀的道長。 經(jīng)常有香客問我愤估,道長帮辟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任灵疮,我火速辦了婚禮织阅,結(jié)果婚禮上壳繁,老公的妹妹穿的比我還像新娘震捣。我一直安慰自己荔棉,他們只是感情好,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布蒿赢。 她就那樣靜靜地躺著润樱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羡棵。 梳的紋絲不亂的頭發(fā)上壹若,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音皂冰,去河邊找鬼店展。 笑死,一個胖子當著我的面吹牛秃流,可吹牛的內(nèi)容都是我干的赂蕴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舶胀,長吁一口氣:“原來是場噩夢啊……” “哼概说!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嚣伐,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤糖赔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后轩端,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體放典,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年基茵,在試婚紗的時候發(fā)現(xiàn)自己被綠了刻撒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡耿导,死狀恐怖声怔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舱呻,我是刑警寧澤醋火,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站箱吕,受9級特大地震影響芥驳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茬高,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一兆旬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怎栽,春花似錦丽猬、人聲如沸宿饱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谬以。三九已至,卻和暖如春由桌,著一層夾襖步出監(jiān)牢的瞬間为黎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工行您, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铭乾,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓娃循,卻偏偏與公主長得像片橡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淮野,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容