##事件分發(fā)原理
1 事件分發(fā)的對象是誰郭脂?
????答:事件
當用戶觸摸屏幕時(View或ViewGroup派生的控件)矩屁,將產(chǎn)生點擊事件(Touch事件)拒垃。
Touch事件相關細節(jié)(發(fā)生觸摸的位置僵朗、時間滋将、歷史記錄衔峰、手勢動作等)被封裝成MotionEvent對象
##主要發(fā)生的Touch事件有如下四種:
????MotionEvent.ACTION_DOWN:0佩脊,按下View(所有事件的開始)
????MotionEvent.ACTION_MOVE:2蛙粘,滑動View
????MotionEvent.ACTION_CANCEL:非人為原因結束本次事件
????MotionEvent.ACTION_UP:1,抬起View(與DOWN對應)
事件列:從手指接觸屏幕至手指離開屏幕威彰,這個過程產(chǎn)生的一系列事件 任何事件列都是以DOWN事件開始出牧,UP事件結束,中間有無數(shù)的MOVE事件
##事件列
????即當一個MotionEvent 產(chǎn)生后歇盼,系統(tǒng)需要把這個事件傳遞給一個具體的 View 去處理,
##1.2 事件分發(fā)的本質(zhì)
????答:將點擊事件(MotionEvent)向某個View進行傳遞并最終得到處理
????即當一個點擊事件發(fā)生后舔痕,系統(tǒng)需要將這個事件傳遞給一個具體的
????View去處理。這個事件傳遞的過程就是分發(fā)過程豹缀。
##1.3 事件在哪些對象之間進行傳遞伯复?
答:Activity、ViewGroup邢笙、View
一個點擊事件產(chǎn)生后啸如,傳遞順序是:
Activity(Window) -> ViewGroup -> View
Android的UI界面是由Activity、ViewGroup氮惯、View及其派生類組合而成的
UI界面
View是所有UI組件的基類
一般Button叮雳、ImageView、TextView等控件都是繼承父類View
ViewGroup是容納UI組件的容器妇汗,即一組View的集合(包含很多子View和子VewGroup)帘不,
其本身也是從View派生的,即ViewGroup是View的子類
是Android所有布局的父類或間接父類:項目用到的布局(LinearLayout杨箭、RelativeLayout等)寞焙,都繼承自ViewGroup,即屬于ViewGroup子類互婿。
與普通View的區(qū)別:ViewGroup實際上也是一個View棺弊,只不過比起View,它多了可以包含子View和定義布局參數(shù)的功能擒悬。
##1.4 事件分發(fā)過程由哪些方法協(xié)作完成?
????答:dispatchTouchEvent() 稻艰、onInterceptTouchEvent()和onTouchEvent()
##Android事件分發(fā)順序:
????Activity(Window) -> ViewGroup -> View
##事件分發(fā)機制詳細流程
????其中:
????super:調(diào)用父類方法
????true:消費事件懂牧,即事件不繼續(xù)往下傳遞
????false:不消費事件,事件也不繼續(xù)往下傳遞 / 交由給父控件onTouchEvent()處理
????接下來尊勿,我將詳細介紹這3個方法及相關流程僧凤。
##dispatchTouchEvent()分發(fā)點擊事件
##onInterceptTouchEvent()分發(fā)攔截事件
##onTouchEvent()事件處理消費
當點擊按鈕的那一刻,會出現(xiàn)(此時是走的默認super方法)
????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyButton: dispatchTouchEvent: 0
?????/MyButton: onTouchEvent: 0
??????MyLinerlayout:onTouchEvent 0
??????MainActivity:onTouchEvent 0
?????/ MainActivity: dispatchTouchEvent: 1
?????/MyLinerlayout: dispatchTouchEvent: 1
?????/MyLinerlayout: onInterceptTouchEvent: 1
?????/MyButton: dispatchTouchEvent: 1
?????/MyButton: onTouchEvent: 1
??????MyLinerlayout:1
??????MainActivity:1
也就是說元扔,事件最終在view層的onTouchEvent()處理結束
##MainActivity
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return true;
????}
??????MainActivity: dispatchTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
代表MainActivity自己把事件消費掉躯保,不繼續(xù)往下分發(fā)
????return false 就代表不處理,事件結束
MainActivity: dispatchTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
##MyLinerlayout
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return true;
????}
?????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MyLinerlayout: dispatchTouchEvent: 1
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return false;
????}
?????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MainActivity: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MainActivity: onTouchEvent: 1
????如果攔截器方法開始攔截返回true澎语,但是viewgroup的onTouchEvent事件默認super()那么事件不會向下分發(fā)途事,會返回給上一級去做處理
@Override
????public boolean onInterceptTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "onInterceptTouchEvent: "+ev.getAction() );
????????return true;
????}
????@Override
????public boolean onTouchEvent(MotionEvent event) {
????????Log.e(TAG, "onTouchEvent: "+event.getAction() );
????????return super.onTouchEvent(event);
????}
????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyLinerlayout: onTouchEvent: 0
?????/MainActivity: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MainActivity: onTouchEvent: 1
????如果攔截器方法開始攔截返回true验懊,viewgroup的onTouchEvent同樣返回true()那么viewgroup就會自己把事件處理掉,事件不會繼續(xù)向下分發(fā)
????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyLinerlayout: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MyLinerlayout: dispatchTouchEvent: 1
?????/MyLinerlayout: onTouchEvent: 1
????如果攔截器方法返回false和super()尸变,事件都會分發(fā)到下一級view义图,view因為是最后一層,他沒有向下分發(fā)的權利召烂,只有選擇處理或者不處理 碱工,view如果都走默認方法
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return super.dispatchTouchEvent(ev);
????}
????@Override
????public boolean onTouchEvent(MotionEvent event) {
????????Log.e(TAG, "onTouchEvent: "+event.getAction() );
????????return super.onTouchEvent(event);
????}
????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyButton: dispatchTouchEvent: 0
?????/MyButton: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MyLinerlayout: dispatchTouchEvent: 1
?????/MyLinerlayout: onInterceptTouchEvent: 1
?????/MyButton: dispatchTouchEvent: 1
?????/MyButton: onTouchEvent: 1
????如果view的dispatchTouchEvent返回true,代表自己消費奏夫,不在向下傳遞
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return true;
????}
????/MainActivity: dispatchTouchEvent: 0
/MyLinerlayout: dispatchTouchEvent: 0
/MyLinerlayout: onInterceptTouchEvent: 0
/MyButton: dispatchTouchEvent: 0
/MainActivity: dispatchTouchEvent: 1
/MyLinerlayout: dispatchTouchEvent: 1
/MyLinerlayout: onInterceptTouchEvent: 1
/MyButton: dispatchTouchEvent: 1
????如果view的dispatchTouchEvent返回false怕篷,onTouchEvent(),返回默認super()酗昼,
????表示不處理廊谓,返回上一級viewgroup的onTouchEvent()去做處理,如果返回true仔雷,
????自己消費蹂析,如果返回false或者super()返回Activity的onTouchEvent去處理
????@Override
????public boolean dispatchTouchEvent(MotionEvent ev) {
????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );
????????return false;
????}
????@Override
????public boolean onTouchEvent(MotionEvent event) {
????????Log.e(TAG, "onTouchEvent: "+event.getAction() );
????????return super.onTouchEvent(event);
????}
????/MainActivity: dispatchTouchEvent: 0
/MyLinerlayout: dispatchTouchEvent: 0
/MyLinerlayout: onInterceptTouchEvent: 0
/MyButton: dispatchTouchEvent: 0
/MyLinerlayout: onTouchEvent: 0
/MainActivity: onTouchEvent: 0
/MainActivity: dispatchTouchEvent: 1
/MainActivity: onTouchEvent: 1
如果view的dispatchTouchEvent()返回super(),會走到本類的onTouchEvent()返回true碟婆,自己消費电抚,事件結束。
????/MainActivity: dispatchTouchEvent: 0
/MyLinerlayout: dispatchTouchEvent: 0
/MyLinerlayout: onInterceptTouchEvent: 0
/MyButton: dispatchTouchEvent: 0
/MyButton: onTouchEvent: 0
/MainActivity: dispatchTouchEvent: 1
/MyLinerlayout: dispatchTouchEvent: 1
/MyLinerlayout: onInterceptTouchEvent: 1
/MyButton: dispatchTouchEvent: 1
/MyButton: onTouchEvent: 1
?????如果view的dispatchTouchEvent()返回super()竖共,onTouchEvent()返回false()或者super()蝙叛,會返回到viewgroup的onTouchEvent(),返回false或者super()公给,最終返回Activity的onTouchEvent()去處理如果viewgroup的onTouchEvent返回true()借帘,代表viewgroup自己消費事件,事件結束淌铐。
????/MainActivity: dispatchTouchEvent: 0
/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyButton: dispatchTouchEvent: 0
?????/MyButton: onTouchEvent: 0
?????/MyLinerlayout: onTouchEvent: 0
?????/MainActivity: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MainActivity: onTouchEvent: 1
##如果Activity肺然,viewgroup,view的分發(fā)事件默認super()腿准,到view的onTouchEvent()返回false()或者super()時候际起,才會完整的走完真?zhèn)€默認處理事件結構,也就是最后的view的onTouchEvent事件一級級的返回吐葱,最終交給Activity的onTouchEvent事件去處理街望。
????@Override
????public boolean onTouchEvent(MotionEvent event) {
????????Log.e(TAG, "onTouchEvent: "+event.getAction() );
????????return false;//此事件是view的事件
????}
????/MainActivity: dispatchTouchEvent: 0
?????/MyLinerlayout: dispatchTouchEvent: 0
?????/MyLinerlayout: onInterceptTouchEvent: 0
?????/MyButton: dispatchTouchEvent: 0
?????/MyButton: onTouchEvent: 0
?????/MyLinerlayout: onTouchEvent: 0
?????/MainActivity: onTouchEvent: 0
?????/MainActivity: dispatchTouchEvent: 1
?????/MainActivity: onTouchEvent: 1
##總結
##**2.1 Activity???** dispatchTouchEvent(MotionEvent ev) -- 事件分發(fā)
????1.返回true 直接消費掉 ,沒有分發(fā);?
????2.返回false,不消費,但是觸摸事件不做處理;
????3.只有返回super.dispatchTouchEvent(ev)事件才會向子view分發(fā),其實是調(diào)用了PhoneWindow的superDispatchTouchEvent(),進而調(diào)用了DecorView的superDispatchTouchEvent,里面又調(diào)用了super.dispatchTouchEvent(),而DecorView是一個FrameLayout
##onTouchEvent(MotionEvent event) --事件處理
????1.返回false和默認(super.onTouchEvent(event)),不做處理;
????2.返回true,消費事件
2.2 ViewGroup
dispatchTouchEvent(MotionEvent ev) -- 事件分發(fā)
????1.返回true 事件被消費了, 事件未分發(fā)
????2.返回false 事件未分發(fā),事件傳遞到父容器的onTouchEvent()
????3.只有返回super.dispatchTouchEvent(ev),事件才會向下走,里面會調(diào)用onInterceptTouchEvent()
onInterceptTouchEvent(MotionEvent ev) -- 事件攔截
????1.返回true,事件攔截,調(diào)用自己的onTouchEvent()
????2.返回false,事件未攔截,分發(fā)給了子view
????3.super.onInterceptTouchEvent(ev)與返回false效果一樣
onTouchEvent(MotionEvent event)
????1.返回false和super.onTouchEvent(event)事件不消費,事件傳遞給父容器
????2.返回true,事件會被消費
2.3 View
dispatchTouchEvent(MotionEvent event)
????因為它最小,沒有子view,所以這個方法其實沒有進行分發(fā)的能力
????1.返回true,事件被消費,
????2.返回false ,事件傳遞到父容器的onTouchEvent()
????3.只有返回super.dispatchTouchEvent(ev),事件才會向下走,里面會調(diào)用自己 onTouchEvent()
onTouchEvent(MotionEvent event)
????1.返回false()或者super()事件不消費,事件傳遞給父容器
????2.返回true,事件會被消費?