出處:https://blog.csdn.net/caifengyao/article/details/65437695html
在Android中,View的結構是樹狀的,因此,當觸發觸摸事件的時候,其事件傳遞也是從上之下一層層的傳遞。下面咱們結合例子來一點點進行分析。java
首先,咱們須要瞭解事件處理中的幾個方法:ide
一、在ViewGroup中,事件分爲dispatchTouchEvent(事件的分發),onInterceptTouchEvent(事件的攔截),onTouchEvent(事件的處理)。post
二、在View中,事件分爲dispatchTouchEvent(事件的分發),onTouchEvent(事件的處理)。spa
下面是demo的界面結構,它是由兩個自定義的ViewGroup和一個自定義的View組成,並分別重寫了它們的以上幾個方法。.net
其中MyViewGroupA代碼以下:3d
public class MyViewGroupA extends LinearLayout { public MyViewGroupA(Context context) { super(context); } public MyViewGroupA(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupA","dispatchTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupA","dispatchTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupA","dispatchTouchEvent_ACTION_UP"); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupA","onInterceptTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupA","onInterceptTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupA","onInterceptTouchEvent_ACTION_UP"); break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupA","onTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupA","onTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupA","onTouchEvent_ACTION_UP"); break; } return super.onTouchEvent(event); } }MyViewGroupB代碼以下:
public class MyViewGroupB extends LinearLayout { public MyViewGroupB(Context context) { super(context); } public MyViewGroupB(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupB","dispatchTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupB","dispatchTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupB","dispatchTouchEvent_ACTION_UP"); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupB","onInterceptTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupB","onInterceptTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupB","onInterceptTouchEvent_ACTION_UP"); break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyViewGroupB","onTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyViewGroupB","onTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyViewGroupB","onTouchEvent_ACTION_UP"); break; } return super.onTouchEvent(event); } }MyView代碼以下:
public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyView","dispatchTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyView","dispatchTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyView","dispatchTouchEvent_ACTION_UP"); break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("MyView","onTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("MyView","onTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("MyView","onTouchEvent_ACTION_UP"); break; } return super.onTouchEvent(event); } }
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("Activity","dispatchTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("Activity","dispatchTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("Activity","dispatchTouchEvent_ACTION_UP"); break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("Activity","onTouchEvent_ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("Activity","onTouchEvent_ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("Activity","onTouchEvent_ACTION_UP"); break; } return super.onTouchEvent(event); } }
一、對以上方法均不做處理,都返回super。這意味着咱們既不攔截,也不消費。htm
你們看輸出結果:blog
I/Activity: dispatchTouchEvent_ACTION_DOWN事件
I/MyViewGroupA: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWN
I/MyView: dispatchTouchEvent_ACTION_DOWN
I/MyView: onTouchEvent_ACTION_DOWN
I/MyViewGroupB: onTouchEvent_ACTION_DOWN
I/MyViewGroupA: onTouchEvent_ACTION_DOWN
I/Activity: onTouchEvent_ACTION_DOWN
I/Activity: dispatchTouchEvent_ACTION_MOVE
I/Activity: onTouchEvent_ACTION_MOVE
I/Activity: dispatchTouchEvent_ACTION_UP
I/Activity: onTouchEvent_ACTION_UP
結合輸出結果,咱們能夠總結出如下的結論:
結合流程圖,不難發現,若是我對事件既不攔截,也不消費,當觸發ACTION_DOWN的時候,事件會通過Activity——MyViewGroupA——MyViewGroupB——MyView一層層的向下進行dispatchTouchEvent(分發)—onInterceptTouchEvent(攔截)調用。當到達最底層MyView後,開始觸發消費操做,由於我均不消費,ACTION_DOWN將由底層一層層向上冒,移交上層處理。當抵達最上層Activity後,說明下層均不消費,以後觸發的ACTION_MOVE和ACTION_UP將再也不向下層分發傳遞,直接交由Activity分發給本身進行處理。
二、咱們將MyVIewGroupB的onInterceptTouchEvent返回值改成true,其餘均是super。這意味着僅僅MyViewGroupB進行事件攔截,但均無消費
輸出結果以下:
I/Activity: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: onTouchEvent_ACTION_DOWN
I/MyViewGroupA: onTouchEvent_ACTION_DOWN
I/Activity: onTouchEvent_ACTION_DOWN
I/Activity: dispatchTouchEvent_ACTION_MOVE
I/Activity: onTouchEvent_ACTION_MOVE
I/Activity: dispatchTouchEvent_ACTION_UP
I/Activity: onTouchEvent_ACTION_UP
結合輸出結果,總結以下:
當觸發ACTION_DOWN的時候,事件依然是從Activity開始一層層向下傳遞,當傳遞到MyViewGroupB時,由於進行了事件攔截,因此執行完onInterceptTouchEvent後再也不向下傳遞,而是直接交由MyViewGroupB的onTouchEvent進行消費處理。因爲咱們是隻攔截,不消費,因此事件向上傳遞,交由上層處理,最終回到Activity。以後觸發的ACTION_MOVE和ACTION_UP也再也不向下傳遞,直接交由Activity分發給本身處理。
三、咱們仍是將MyViewGroupB的onInterceptTouchEvent返回super,可是將他的onTouchEvent返回true。這意味着咱們不攔截,可是由MyViewGroupB進行事件處理。
輸出結果以下:
I/Activity: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWN
I/MyView: dispatchTouchEvent_ACTION_DOWN
I/MyView: onTouchEvent_ACTION_DOWN
I/MyViewGroupB: onTouchEvent_ACTION_DOWN
I/Activity: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupA: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupA: onInterceptTouchEvent_ACTION_MOVE
I/MyViewGroupB: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupB: onTouchEvent_ACTION_MOVE
I/Activity: dispatchTouchEvent_ACTION_UP
I/MyViewGroupA: dispatchTouchEvent_ACTION_UP
I/MyViewGroupA: onInterceptTouchEvent_ACTION_UP
I/MyViewGroupB: dispatchTouchEvent_ACTION_UP
I/MyViewGroupB: onTouchEvent_ACTION_UP
結合輸出結果,總結以下:
能夠看出,當觸發ACTION_DOWN的時候,事件的分發傳遞過程和1的時候同樣,從Activity開始一層層向下傳遞,最終傳遞到最底層MyView,觸發消費操做,而後MyView將消費操做移交上層處理,而後到達MyViewGroupB的onTouchEvent,而且進行了消費處理,事件處理到此不在向上移交。當觸發ACTION_MOVE和ACTION_UP操做時,事件依然須要由Activity開始向下分發傳遞,可是當傳遞到MyViewGroupB後,因爲其消費了ACTION_DOWN,事件將再也不繼續向下分發,而是直接由MyViewGroupB分發給本身的onTouchEvent進行繼續處理。事件處理也再也不向上移交。
四、將MyViewGroupB的onInterceptTouchEvent和onTouchEvent的返回值均改成true。這意味着既攔截,又消費。
輸出結果以下:
I/Activity: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: dispatchTouchEvent_ACTION_DOWN
I/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWN
I/MyViewGroupB: onTouchEvent_ACTION_DOWN
I/Activity: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupA: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupA: onInterceptTouchEvent_ACTION_MOVE
I/MyViewGroupB: dispatchTouchEvent_ACTION_MOVE
I/MyViewGroupB: onTouchEvent_ACTION_MOVE
I/Activity: dispatchTouchEvent_ACTION_UP
I/MyViewGroupA: dispatchTouchEvent_ACTION_UP
I/MyViewGroupA: onInterceptTouchEvent_ACTION_UP
I/MyViewGroupB: dispatchTouchEvent_ACTION_UP
I/MyViewGroupB: onTouchEvent_ACTION_UP
結合輸出結果,總結以下:
當觸發ACTION_DOWN的時候,依然從Activity開始向下傳遞,當到達MyViewGroupB的是,由於在onInterceptTouchEvent進行了攔截操做,所以再也不繼續向下分發傳遞,而是交由MyViewGroupB的onTouchEvent進行處理消費。MyViewGroupB的onTouchEvent返回的是true,說明它決定對ACTION_DOWN進行處理,所以事件也就再也不移交上層處理。當觸發ACTION_MOVE和ACTION_UP的時候,事件仍是從Activity開始向下傳遞,當到達MyViewGroupB的時候,因爲以前進行了攔截操做,所以,MyViewGroupB直接將事件分發給本身的onTouchEvent進行處理,不在向下分發傳遞。事件處理也再也不向上層移交。
案例Demo下載地址:點擊打開連接