完全理解android事件分發機制

明天的码报图:重要函數

码报开奖结果本期 www.iwqgw.icu 筆者此次主要提及最常用的幾個函數: 
(其間區別看源碼很容易理解,此處直接給上結果) 
onClick():這個函數是是View提供給我們的OnClickListener這個接口中的函數,在這里可以自定義對點擊事件的處理邏輯?;嵩趏nTouchEvent()中進行調用。 
onTouch():這個函數是View提供給我們的OnTouchListener這個接口中的函數,在這里面可以自定義對觸摸事件的處理邏輯。 
onTouchEvent():這個函數是view內部的觸摸事件的處理方式,其間包括獲取焦點,調用onClick()等等。 
dispatchTouchEvent():這個是View的事件分發函數,在ViewGroup中進行重寫。在View中其間會調用onTouchEvent(),在ViewGroup中其間會調用onInterceptTouchEvent()和onTouchEvent()。 
onInterceptTouchEvent():這個函數是事件攔截函數,是ViewGroup才有的函數。

重要函數執行順序

此處我們通過一個很簡單的例子進行說明,示例: 
這里寫圖片描述 
示例xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<com.example.double2.dispatchevent.LinearLayoutA
    xmlns:android="//schemas.android.com/apk/res/android"
    android:id="@+id/ll_a"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_dark"
    android:padding="30dp"
    android:orientation="vertical"
    >

    <com.example.double2.dispatchevent.LinearLayoutB
        android:id="@+id/ll_b"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:padding="30dp"
        android:orientation="vertical"
        >

        <com.example.double2.dispatchevent.LinearLayoutC
            android:id="@+id/v_c"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            />
    </com.example.double2.dispatchevent.LinearLayoutB>
</com.example.double2.dispatchevent.LinearLayoutA>1234567891011121314151617181920212223242526272829303112345678910111213141516171819202122232425262728293031

由外到里主要是三個LinearLayout,分別為A、B、C。筆者分別在五個關鍵函數中加上了Log,最終點擊一下,輸出的值如下:

01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_C 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C 
01-12 01:28:58.136 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_C 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_C 
01-12 01:28:58.203 2442-2442/com.example.double2.dispatchevent D/XJJ: onClick_C

如上,我們可以看到五個函數的大致執行順序如下:

  1. dispatchTouchEvent()

  2. onInterceptTouchEvent()

  3. onTouch()

  4. onTouchEvent()

  5. onClick()

好奇的讀者肯定會問,為什么事件分發執行了兩次呢? 
其實很簡單,因為的確有兩個分發的事件,一次是“手指按下”的事件,一次是“手指抬起”的事件。我們可以看到,只有在“手指抬起”的時候,才會觸發onClick()事件。

此處為了便于大家理解,也附上一張事件分發的圖: 
這里寫圖片描述

控制事件分發

然而還有一個值得我們在意的事情,就是onTouch()以及onTouchEvent()只有在C中執行,而在B和A的就不執行了。 
此處,我們就必須再講一點了。

dispatchTouchEvent()、onInterceptTouchEvent() 、onTouch()、onTouchEvent()這四個函數,返回值為false的時候,事件會繼續向下分發,一旦返回值為true,事件就不再向下分發。 
而onClick()沒有返回值

根據這點我們可以知道,一定是C的onTouchEvent()中返回了true,我們將其更改后再看一下效果。 
原來的代碼為:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("XJJ","onTouchEvent_C");        return super.onTouchEvent(event);
    }1234512345

更改后:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("XJJ","onTouchEvent_C");        return false;
    }1234512345

效果:

01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_C 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_C 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_B 
01-12 01:24:06.250 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_B 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_B 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_B 
01-12 01:24:06.360 2442-2442/com.example.double2.dispatchevent D/XJJ: onClick_B

這樣操作之后,我們可以發現,“手指按下”時,onTouch()以及onTouchEvent()事件就可以傳遞到B了。但是同時,我們也可以發現,當“手指抬起”時,C的onTouch()以及onTouchEvent()事件就不會執行了。

當然,如果需要onTouch()以及onTouchEvent()事件傳遞到A,那么只需要將B的onTouchEvent()也返回false即可。(此處就不重復演示了)

那么如果onTouchEvent()返回值設置為true了之后,是不是onClick()事件是不是就不會執行了呢?效果如下:

01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_C01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C01-12 01:39:21.560 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_C01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C01-12 01:39:21.617 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_C123456789101112131415123456789101112131415

onClick()的確是不會執行了,如此我們也嘗試一下onTouch()返回值設置為true,效果如下:

01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_C 
01-12 01:40:41.101 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_C 
01-12 01:40:41.173 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_C

如此,我們可知,當onTouch()返回值設置為true的時候,onTouchEvent()的確是不會執行了。

到這里,我們其實只剩下對onInterceptTouchEvent() 的分析了,為何沒有dispatchTouchEvent()了呢? 
因為dispatchTouchEvent()是事件分發的函數,對View而言,我們阻止它內部的事件分發是沒有什么意義的,而我們要控制ViewGroup的事件分發則是通過onInterceptTouchEvent() 來執行的。

如此我們便假設一個應用場景,A包括B,B包括C,B為橫向滑動,C為豎向滑動,當橫向滑動的加速度大于豎向滑動的加速度的時候,我們僅僅讓B響應事件,而不把事件傳遞給C。

我們可以通過onInterceptTouchEvent() 來實現,僅僅只需將B的onInterceptTouchEvent()返回值設置為true即可,效果如下:

01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_B 
01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_B 
01-12 01:50:18.513 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_B 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_A 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: onInterceptTouchEvent_A 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: dispatchTouchEvent_B 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouch_B 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: onTouchEvent_B 
01-12 01:50:18.621 2442-2442/com.example.double2.dispatchevent D/XJJ: onClick_B

來源:CSDN

上一篇: Android和H5交互-框架篇

下一篇: Android多線程,讓耗時的操作去后臺運行吧

分享到: 更多
飞艇计划全天专业版 欢乐二八杠游戏下载 3d都有哪些玩法 易网重庆老时时开奖 万人炸金花官方下载 un时时彩计划软件 一分快三稳赚倍投方案 11选5稳赚技巧任7杀号 什么是隔一投注法 双色球开奖日期 双色球计划软件哪个准 彩票开奖双色球预测 上海时时票开奖结果查询 全天北京pk10专家计划 gucci意大利官网 澳洲赛车统一开奖吗