Android事件分發(fā)機制詳解與實戰(zhàn)剖析建丧,一張事件分發(fā)流程圖,讓你徹底搞明白

本文為自己多年來在Android實戰(zhàn)開發(fā)過程中總結歸納的一些常見問題波势,現(xiàn)在分享出來希望對初學者有所幫助翎朱。

本文出自門心叼龍的博客,轉載請注明出處: https://blog.csdn.net/geduo_83/article/details/86560896

事件分發(fā)是Android開發(fā)過程中的重點又是難點艰亮, 一張事件分發(fā)流程圖闭翩,讓你徹底搞明白。網(wǎng)上有很多文章寫事件分發(fā)迄埃,感覺都沒有講明白疗韵,恭喜你,今天你看到好文章了侄非,你徹底搞清楚...

目錄

[1.在Android操作系統(tǒng)中蕉汪,擁有事件傳遞功能的類都有哪些?]
[2.觸摸事件的類型逞怨?]
[3.事件傳遞的三個階段者疤?]
[4.簡述View的事件傳遞機制?]
[5.簡述ViewGroup的事件傳遞機制?]
[6.事件分發(fā)流程圖]
[7.實戰(zhàn)案例]


1.在Android操作系統(tǒng)中叠赦,擁有事件傳遞功能的類都有哪些驹马?

  • Activity:擁有dispathTouchEvent和onTouchEvent方法
  • View:擁有dispathTouchEvent和onTouchEvent方法
  • ViewGroup:擁有dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent

2.觸摸事件的類型糯累?

主要有三種:

  • ACTION_DOWN : 手指的按下操作
  • ACTION_MOVE:手指按下后算利,松開手之前,輕微移動所觸發(fā)的事件
  • ACTION_UP:手指離開屏幕的操作

3.事件傳遞的三個階段泳姐?

  • 3.1 按照事件進行劃分

    image
  • 3.2 按照View進行劃分
image

結論:無論是View還是ViewGroup效拭,不管他是DispatchTouchEvent還是onTouchEvent方法,方法返回true胖秒、返回false的處理邏輯都是一樣的缎患,只是調(diào)用父類的同名方法的時候處理的邏輯有所不同,View偏重消費阎肝、ViewGourp偏重分發(fā)

4.簡述View的事件傳遞機制挤渔?

觸摸事件的傳遞流程是從dispatchTouchEvent開始的,如果不進行人工干預盗痒,則事件將會依照View樹的嵌套層次從外層向內(nèi)層傳遞蚂蕴,到達最內(nèi)層的View時低散,就由它的onTouchVent方法處理
如果事件在傳遞過程中俯邓,進行了人工干預,事件分發(fā)函數(shù)返回true表示自行消費熔号,返回父類的同名方法則該事件傳遞給自身的onTouchEvent進行處理稽鞭,返回false表示該事件會回傳給父view的onTouchEvent方法進行處理,此時后面的事件都接受不到了引镊,最后由哪個View處理朦蕴,以后的所有事件都交由它來處理
如果事件在傳遞過程中,進行了人工干預弟头,事件處理函數(shù)吩抓,返回true和調(diào)用同名方法表示該事件被消費,返回false則表示該事件回傳給父類的同名方法進行處理
事件觸發(fā)是先觸發(fā)onTouch赴恨,再觸發(fā)onClick疹娶,如果onTouch方法返回tue,表示消費掉該事件伦连,不在繼續(xù)進行事件傳遞雨饺,onClick也不會被調(diào)用,如果onTouch方法返回false惑淳,則繼續(xù)會事件傳遞额港,onClick會被調(diào)用

5.簡述ViewGroup的事件傳遞機制?

觸摸事件的傳遞順序是由Activity到ViewGroup,再由ViewGroup遞歸傳遞給他的子View歧焦,ViewGroup通過onInterceptTouchEvent方法對事件進行攔截移斩,如果該方法返回true,則事件不會繼續(xù)往下傳遞給子View,如果返回false或者是調(diào)用super.onInterceptTouchEvent,則事件會繼續(xù)會傳遞給子View
如果事件在傳遞過程中向瓷,進行了人工干預忍宋,事件分發(fā)函數(shù)返回true表示事件被自行消費,返回false风罩,則回傳給父View的onTouchEvent進行處理糠排,此時后面的事件都接受不到了,調(diào)用同名方法則繼續(xù)傳遞
如果事件在傳遞過程中超升,進行了人工干預入宦,事件處理函數(shù),返回true則表示該事件被消費室琢,返回false和調(diào)用同名方法則表示該事件回傳給父類的同名方法進行處理

6.事件分發(fā)流程圖

一張android事件分發(fā)流程乾闰,讓你徹底搞明白Android的事件分發(fā)機制

image

ViewGroup的事件分發(fā)的偽代碼:

 public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if (onInterceptTouchEvent(ev)) {
            if (!(mOnTouchListener != null && mOnTouchListener.onTouchEvent(ev))) {
                consume = onTouchEvent(ev);
            }
        } else {
            consume = child.dispatchTouchEvent(ev);
        }
        return consume;
    }

    public void onTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if (mOnClickListener != null) {
            mOnClickListener.onClick(this);
            consume = true;
        }
        return consume;
    }

View的事件分發(fā)的偽代碼:

 public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        consume = onTouchEvent(ev);
        return consume;
    }

    public void onTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if (mOnClickListener != null) {
            mOnClickListener.onClick(this);
            consume = true;
        }
        return consume;
    }

7.實戰(zhàn)案例

實現(xiàn)效果如下,底部的行程詳情可以往上拖動覆蓋在地圖之上盈滴,也可以往下拖動停止在屏幕的正中位置涯肩,地圖相關操作:放大、縮小巢钓、移動都能正常的響應病苗,怎么實現(xiàn)?下面就是具體的源碼實現(xiàn)過程

image
image.gif

?

  • 7.1 事件分發(fā)處理
mTransparentView = findViewById(R.id.view_tansparent);
mTransparentView.setListener(new TransparentView.TouchEventListener() {
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return mMapView.dispatchTouchEvent(event);
    }
});
mScrollView = findViewById(R.id.view_scrollview);
mScrollView.setListener(new TransparentView.TouchEventListener() {
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Rect rect = new Rect();
        mTransparentView.getLocalVisibleRect(rect);
        if(rect.contains((int)event.getX(),(int)event.getY())){
            return true;
        }else{
            return false;
        }
    }
});
  • 7.2 自定義ViewTransparentView
public class TransparentView extends View {
    TouchEventListener mListener;
    public interface TouchEventListener{
        boolean dispatchTouchEvent(MotionEvent event);
    }
    public TransparentView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if(mListener != null){
            return  mListener.dispatchTouchEvent(event);
        }else{
            return super.dispatchTouchEvent(event);
        }
    }

    public void setListener(TouchEventListener listener) {
        mListener = listener;
    }
}
image.gif
  • 7.3 自定義TransScrollView
public class TransScrollView extends NestedScrollView {
    public TransparentView.TouchEventListener mListener;

    public TransScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mListener != null && mListener.dispatchTouchEvent(ev)) {
            return false;
        }
        return super.onInterceptTouchEvent(ev);
    }

    public void setListener(TransparentView.TouchEventListener listener) {
        mListener = listener;
    }
}
image.gif
  • 7.4 布局文件
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <com.amap.api.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        />
    <com.zhijiaxing.travel.trip.record.view.TransScrollView
        android:id="@+id/view_scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"

        >
        <com.zhijiaxing.travel.trip.record.view.TransparentView
            android:id="@+id/view_tansparent"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:background="#00000000"
            />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff"
            android:orientation="vertical"
            >
        </LinearLayout>

    </LinearLayout>
    </com.zhijiaxing.travel.trip.record.view.TransScrollView>
</FrameLayout>
image.gif
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末症汹,一起剝皮案震驚了整個濱河市硫朦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌背镇,老刑警劉巖咬展,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瞒斩,居然都是意外死亡破婆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門胸囱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祷舀,“玉大人,你說我怎么就攤上這事旺矾∶镳校” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵箕宙,是天一觀的道長嚎朽。 經(jīng)常有香客問我,道長柬帕,這世上最難降的妖魔是什么哟忍? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任狡门,我火速辦了婚禮,結果婚禮上锅很,老公的妹妹穿的比我還像新娘其馏。我一直安慰自己,他們只是感情好爆安,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布叛复。 她就那樣靜靜地躺著,像睡著了一般扔仓。 火紅的嫁衣襯著肌膚如雪褐奥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天翘簇,我揣著相機與錄音撬码,去河邊找鬼。 笑死版保,一個胖子當著我的面吹牛呜笑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播彻犁,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼叫胁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了袖裕?” 一聲冷哼從身側響起曹抬,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎急鳄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堰酿,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡疾宏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了触创。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坎藐。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哼绑,靈堂內(nèi)的尸體忽然破棺而出岩馍,到底是詐尸還是另有隱情,我是刑警寧澤抖韩,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布蛀恩,位于F島的核電站,受9級特大地震影響茂浮,放射性物質(zhì)發(fā)生泄漏双谆。R本人自食惡果不足惜壳咕,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顽馋。 院中可真熱鬧谓厘,春花似錦、人聲如沸寸谜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熊痴。三九已至住练,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愁拭,已是汗流浹背讲逛。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岭埠,地道東北人盏混。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像惜论,于是被迫代替她去往敵國和親许赃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

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