當(dāng)我們手指觸摸屏幕是觸摸時間開始一級一級向下傳遞
開始-->摁下-->down事件-->滑動-->move事件-->抬起手指-->up事件-->結(jié)束
|-->非人為取消-->cancel事件|
MotionEvent在手機View中的傳遞就是事件分發(fā)的本質(zhì)
我們可以簡單的把應(yīng)用UI組件分成三級掌腰, Activity(Windows級)乎完, ViewGroup, View僚饭。
ViewGropu繼承View因此它也可以作為子組件View放在其他ViewGroup下這樣才能形成層級復(fù)雜的布局假瞬。
在這些組件中參與事件分發(fā)的方法分別有:dispatchTouchEvent(); onInterceptTouchEvent(); onTouchEvent();
dispatchTouchEvent() 分發(fā)點擊事件考婴, 當(dāng)點擊事件能都傳到當(dāng)前View時調(diào)用
onInterceptTouchEvent() 是否攔截事件,只存在于Viewgroup, 在dispatchTouchEvent()中被調(diào)用
onTouchEvnet() 處理點擊事件, 在dispachTouchEvnet()內(nèi)部調(diào)用
分發(fā)順序:Activity(Windows)-->ViewGroup-->View
下面是事件流程圖: true/false為相應(yīng)方法返回值, super則是調(diào)用默認(rèn)實現(xiàn)
- 事件傳遞到activity , dispatchTouchEvent返回ture/false結(jié)束傳遞赋咽, 執(zhí)行spuer向下傳遞旧噪。
- 事件傳遞到Viewgroup dispatchTouchevent返回true表示攔截不處理直接結(jié)束傳遞, 返回false表示攔不處理讓上層Activity處理即Activity的onTouchEvent處理脓匿,Activity的 onTouchEvent不管返回true/false結(jié)束傳遞淘钟。執(zhí)行super則繼續(xù)向下傳遞
- 事件傳遞到ViewGroup的onInterTouchevent, onInterTouchEvent返回true表示本ViewGroup將攔截事件,事件傳遞給ViewGroup的onTouchEvent進(jìn)行處理陪毡。
- ViewGroup的onToucheEvent返回True則事件結(jié)束處理米母,返回super或false則傳遞上層Activity的onTouchEvent再次處理。這里返回fase(super)默認(rèn)返回false, 相當(dāng)于dipatchTouchEvent返回了false,于是可以傳遞到上層的onTouchEvent事件中
- onInterceptTouchEvent接收傳遞過來的事件返回false或默認(rèn)super(默認(rèn)false)表示ViewGroup不攔截事件繼續(xù)向下傳遞
- 這樣一層一層傳遞到手指所摁下的View上毡琉,View dipatchTouchEvent返回true表示攔截不處理事件傳遞結(jié)束铁瞒,返回false則需要傳遞到上層的onToucheEvent進(jìn)行處理,返回super表示傳遞給當(dāng)前View的onTouchEvent進(jìn)行處理
- 同樣View onToucheEvent返回true則消耗事件結(jié)束傳遞桅滋,返回false則向上層onTouchEvent傳遞慧耍,也就是dispatchToucheEvent返回了false。
至此一個事件的傳遞過程各種情況分析完成
MOVE事件丐谋; UP事件
- 默認(rèn)情況下雖然ViewGroup onInterceptTouchEvent對DOWN事件返回了false, 但后續(xù)MOVE芍碧,UP依然傳遞給他的onInterceptTouchEvent方法;
- DOWN事件傳遞到View的onTouchEvent方法并返回true時,MOVE和UP也將傳遞到這個onTouchEvent中
- ViewGroup 的onInterceptTouchEvent一旦返回true則不再被調(diào)用号俐,MOVE和UP事件則直接到ViewGroup的onToucheEnent中不經(jīng)過onTnterceptTouchEnvent泌豆。
- DOWN事件傳遞到View并返回true, ViewGroup的onInterceptTouchEvnet返回true攔截MOVE事件,該事件并沒有傳遞給ViewGroup 的onTouchEvnet將會被系統(tǒng)變成一個CANCEL事件傳給View的OntouchEvent; ViewGroup 的onInterceptToucheEvent一旦返回true后續(xù)事件就不會再傳過來了
- 如果ViewGroup攔截了半路的MOVE同樣也是變成CANCEL事件傳遞到之前處理事件的View中
注意:
- View 的dispatchTouchEvent只有下面三個都為真才返回true
第一個條件:mOnTouchListener != null吏饿;
第二個條件:(mViewFlags & ENABLED_MASK) == ENABLED踪危;
第三個條件:mOnTouchListener.onTouch(this, event)蔬浙;
- onTouch 執(zhí)行高于onClick. onClick在onTouchEvent方法里的performClick執(zhí)行
onTouch 返回false沒有消費,dispatchTouchEvent返回false陨倡,繼續(xù) onTouchEvent 然后Onclick - 如果控件為 非enable則onTouch不會執(zhí)行敛滋,如果想監(jiān)聽touch則重寫onTouchEvent
- 注冊了Touch事件則DOWN,MOVE兴革,UP都會觸發(fā)绎晃,只有dispatchTouchEvent返回false其他不會執(zhí)行
- dispatchTouchEvent和onTouchEvnet返回true消費事件停止傳遞
- 如果dispatchTouchEvnet返回true那么收到DOWN的也會收到MOVE和UP
- 如果onTouchEvent消費事件返回true, MOVE和UP直接傳到改View后不再下傳而直接onTouchEvent結(jié)束