溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android事件流程詳解

發(fā)布時間:2020-07-30 14:06:15 來源:網(wǎng)絡(luò) 閱讀:409 作者:GeekTrain 欄目:移動開發(fā)

Android事件流程詳解

    網(wǎng)絡(luò)上有不少博客講述了android的事件分發(fā)機(jī)制和處理流程機(jī)制,但是看過千遍,總還是覺得有些迷迷糊糊,因此特地抽出一天事件來親測下,向像我一樣的廣大入門程序員詳細(xì)講述android事件背后的故事,話不多說,上干貨。

    android整個事件流程主要牽扯到dispatchTouchEvent(),onInterceptTouchEvent(),

onTouchEvent()這三個方法,下表來說明這三個方法的功能和分布場景:

    表1:

方法名稱功解解說ActivityViewGroupView
dispatchTouchEvent()事件分發(fā)YESYESYES
onInterceptTouchEvent()事件攔截NOYESNO
onTouchEvent()事件處理YESYESYES

  先來分析下Touch事件:所有Touch事件發(fā)生時會調(diào)用當(dāng)前Activity的dispatchTouchEvent()方


法來分發(fā)事件,Activity的dispatchTouchEvent()方法最終會調(diào)用PhoneWindow類中的


superDispatchTouchEvent方法,最終邏輯就是該activity會調(diào)用ViewGroup類中的


dispatchTouchEvent()進(jìn)行隧道式分發(fā)事件(按布局元素由外向內(nèi)分發(fā)),如本案例中的分發(fā)流程


為TouchTraining    ->  TouchViewGroup -> TouchView,需要注意的是,當(dāng)你在Activit中的


dispatchTouchEvent()中直接返回具體的布爾值(無論是true還是false),Touch事件直接會被


消費在該方法中,不會再進(jìn)行下來的事件分發(fā)流程,因此必須在activity的dispatchTouchEvrent


返回super.dispatchTouchEvent()來進(jìn)行事件分發(fā)流程。下面進(jìn)行案例說明分析:


  首先在定義自己的View和ViewGroup,重寫表1它們各自支持的事件流程方法,我這里自定ViewGroup


繼承的是LinearLayout(只要繼承的是ViewGroup都一樣),然后分別在Activity的布局文件中加入自定


義的控件,接著在Activity中也重寫它支持的事件流程方法。


activity_touchtrain.xml

        

Android事件流程詳解


TouchView(自定義View類)

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    Log.e(TAG, "dispatchTouchEvent分發(fā)事件"+ TouchEventUtil.getTouchAction(event.getAction()));
    return super.dispatchTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Log.e(TAG, "onTouchEvent處理事件"+ TouchEventUtil.getTouchAction(ev.getAction()));
    return super.onTouchEvent(ev);
}

TouchViewGroup(自定義ViewGroup類)

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    Log.e(TAG, "dispatchTouchEvent分發(fā)事件" + TouchEventUtil.getTouchAction(ev.getAction()));
    return super.dispatchTouchEvent(ev);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.e(TAG, "onInterceptTouchEvent攔截事件"+ TouchEventUtil.getTouchAction(ev.getAction()));
    return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Log.e(TAG, "onTouchEvent處理事件"+ TouchEventUtil.getTouchAction(ev.getAction()));
    return super.onTouchEvent(ev);
}

TouchTraining(Activity)

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    Log.e(TAG, "dispatchTouchEvent分發(fā)事件"+ TouchEventUtil.getTouchAction(ev.getAction()));
    return super.dispatchTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Log.e(TAG, "onTouchEvent處理事件"+ TouchEventUtil.getTouchAction(ev.getAction()));
    return super.onTouchEvent(ev);
}

TouchEventUtils(工具類,獲取當(dāng)前事件類型)

public static String getTouchAction(int actionId) {
    String actionName = "Unknow:id=" + actionId;
    switch (actionId) {
        case MotionEvent.ACTION_DOWN:
            actionName = "ACTION_DOWN";
            break;
        case MotionEvent.ACTION_MOVE:
            actionName = "ACTION_MOVE";
            break;
        case MotionEvent.ACTION_UP:
            actionName = "ACTION_UP";
            break;
        case MotionEvent.ACTION_CANCEL:
            actionName = "ACTION_CANCEL";
            break;
        case MotionEvent.ACTION_OUTSIDE:
            actionName = "ACTION_OUTSIDE";
            break;
    }
    return actionName;
}


案例分析


方案1

條件
控件名稱dispatchTouchEvent返回值onInterceptTouchEvent 返回值onTouchEvent 返回值
TouchTraining
super.dispatchTouchEvent(ev)----super.onTouchEvent(ev)
TouchViewGroupfalsesuper.onInterceptTouchEvent(ev)super.onTouchEvent(ev)
TouchViewsuper.dispatchTouchEvent(ev)----super.onTouchEvent(ev)

運行結(jié)果:

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_UP


結(jié)果分析:Touch事件開始,調(diào)用TouchTraining的dispatchTouchEvent把事件分發(fā)TouchViewGroup

的dispatchTouchEvent,TouchViewGroup的dispatchTouchEvent返回false,事件停止向下傳遞,同

時事件并沒有消費,但由于該事件來自TouchTraining(Activity),所以最終返回給TouchTraining

的onTouchEvent進(jìn)行消費。


方案2

條件
控件名稱dispatchTouchEvent返回值onInterceptTouchEvent 返回值onTouchEvent 返回值
TouchTraining
super.dispatchTouchEvent(ev)----super.onTouchEvent(ev)
TouchViewGrouptruesuper.onInterceptTouchEvent(ev)super.onTouchEvent(ev)
TouchViewsuper.dispatchTouchEvent(ev)----super.onTouchEvent(ev)

運行結(jié)果:

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_UP


結(jié)果分析:Touch事件由TouchTraining的dispatchTouchEvent不斷向TouchViewGroup分發(fā),

TouchViewGroup的dispatchTouchEvent返回true,TouchViewGroup在dispatchTouchEvent中不斷消

費來自TouchTraining的dispatchTouchEvent分發(fā)的事件。


方案3

條件
控件名稱dispatchTouchEvent返回值onInterceptTouchEvent 返回值onTouchEvent 返回值
TouchTraining
super.dispatchTouchEvent(ev)----super.onTouchEvent(ev)
TouchViewGroupsuper.onInterceptTouchEvent(ev)truesuper.onTouchEvent(ev)
TouchViewsuper.dispatchTouchEvent(ev)----super.onTouchEvent(ev)

運行結(jié)果:

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: onInterceptTouchEvent攔截事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_UP


結(jié)果分析:Touch事件發(fā)生,調(diào)用TouchTraining的dispatchTouchEvent分發(fā)事件到TouchViewGroup

的dispatchTouchEvent,TouchViewGroup的dispatchTouchEvent返回super.onInterceptTouchEvent(ev)進(jìn)

行事件分發(fā),事件向下傳遞給TouchViewGroup的onInterceptTouchEvent,TouchViewGroup的onInterceptTouchEvent返回true,事件被攔截并傳遞給TouchViewGroup的onTouchEvent進(jìn)行消費,TouchViewGroup的onTouchEvent返回super.dispatchTouchEvent(ev),對Touch事件未消費并返回給上級控件的onTouchEvent進(jìn)行消費,由于TouchViewGroup的Touch事件來自TouchTraining,所以最后 由TouchTraining的onTouchEvent進(jìn)行消費。


方案4


條件
控件名稱dispatchTouchEvent返回值onInterceptTouchEvent 返回值onTouchEvent 返回值
TouchTraining
super.dispatchTouchEvent(ev)----super.onTouchEvent(ev)
TouchViewGroupsuper.onInterceptTouchEvent(ev)falsesuper.onTouchEvent(ev)
TouchViewsuper.dispatchTouchEvent(ev)----super.onTouchEvent(ev)


運行結(jié)果:

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: onInterceptTouchEvent攔截事件ACTION_DOWN

com.training.cj.mytraining E/TouchView: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchView: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchTraining: onTouchEvent處理事件ACTION_UP


結(jié)果分析:Touch事件發(fā)生,調(diào)用TouchTraining的dispatchTouchEvent分發(fā)事件到TouchViewGroup的dispatchTouchEvent,TouchViewGroup的dispatchTouchEvent返回super.onInterceptTouchEvent(ev),繼續(xù)分發(fā)向下傳遞事件到TouchViewGroup的onInterceptTouchEvent,TouchViewGroup的onInterceptTouchEvent返回false,繼續(xù)分發(fā)向下傳遞事件到TouchView的dispatchTouchEvent,TouchView的dispatchTouchEvent返回super.dispatchTouchEvent(ev),繼續(xù)分發(fā)向下傳遞事件到TouchView的onTouchEvent,TouchView的onTouchEvent返回super.onTouchEvent(ev),事件沒有消費,返回給上級TouchViewGroup的onTouchEvent進(jìn)行消費,TouchViewGroup的

onTouchEvent返回super.onTouchEvent(ev),繼續(xù)返回給上級TouchTraining的onTouchEvent進(jìn)行消費。


方案5:

條件
控件名稱dispatchTouchEvent返回值onInterceptTouchEvent 返回值onTouchEvent 返回值
TouchTraining
super.dispatchTouchEvent(ev)----super.onTouchEvent(ev)
TouchViewGroupsuper.onInterceptTouchEvent(ev)falsesuper.onTouchEvent(ev)
TouchViewtrue----super.onTouchEvent(ev)


運行結(jié)果:

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchViewGroup: onInterceptTouchEvent攔截事件ACTION_DOWN

com.training.cj.mytraining E/TouchView: dispatchTouchEvent分發(fā)事件ACTION_DOWN

com.training.cj.mytraining E/TouchView: onTouchEvent處理事件ACTION_DOWN

com.training.cj.mytraining E/TouchTraining: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchViewGroup: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchViewGroup: onInterceptTouchEvent攔截事件ACTION_UP

com.training.cj.mytraining E/TouchView: dispatchTouchEvent分發(fā)事件ACTION_UP

com.training.cj.mytraining E/TouchView: onTouchEvent處理事件ACTION_UP


結(jié)果分析:Touch事件發(fā)生,調(diào)用TouchTraining的dispatchTouchEvent分發(fā)事件到TouchViewGroup的dispatchTouchEvent,該方法返回super.dispatchTouchEvent(ev),繼續(xù)分發(fā)事件到TouchViewGroup的onInterceptTouchEvent,該方法返回false,繼續(xù)分發(fā)事件到TouchView的dispatchTouchEvent,該方法返回super.dispatchTouchEvent(ev),繼續(xù)分發(fā)事件到onTouchEvent,由于onTouchEvent返回true,表示消費了事件,Touch事件終止。


    好了,本期的Touch事件分析到這里就結(jié)束了,另外,還有一個小細(xì)節(jié)需要注意的是,在View和View Group中的onTouchEvent方法默認(rèn)返回false,View Group中的onInterceptTouchEvent也默認(rèn)返回false。所以上面5種方案描述出了所有的Touch事件傳遞可能。了解Touch事件的分發(fā)和消費機(jī)制,更有利于我們自定義控件,當(dāng)然我們在自定義控件時,盡量不要重寫dispatchTouchEvent這個方法。

    本貼參考博客:http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI