準(zhǔn)備工作
對(duì)于Android事件處理分為兩類:
對(duì)于Activity和View: 只有兩種事件:
分發(fā): dispatchTouchEvent函數(shù)
消費(fèi): onTouchEvent函數(shù)對(duì)于ViewGroup: 全部三種事件:
分發(fā): dispatchTouchEvent函數(shù)
攔截:onInterceptTouchEvent函數(shù)
消費(fèi): onTouchEvent函數(shù)
重寫一個(gè)ViewGroup和一個(gè)View硝皂,代碼如下
EventViewGroup.java
public class EventViewGroup extends LinearLayout {
public EventViewGroup(Context context) {
super(context);
}
public EventViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("event","----------->dispatchTouchEvent:::ViewGroup----" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e("event","----------->onInterceptTouchEvent:::ViewGroup----" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("event","----------->onTouchEvent:::ViewGroup----" + event.getAction());
return super.onTouchEvent(event);
}
}
EventView.java
public class EventView extends View {
public EventView(Context context) {
super(context);
}
public EventView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("event", "----------->dispatchTouchEvent:::View----" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("event", "----------->onTouchEvent:::View----" + event.getAction());
return super.onTouchEvent(event);
}
}
MainActivity.java
package com.gerry.dispatchevent;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import com.gerry.dispatchevent.view.EventView;
import com.gerry.dispatchevent.view.EventViewB;
import com.gerry.dispatchevent.viewgroup.EventViewGroup;
import com.gerry.dispatchevent.viewgroup.EventViewGroupB;
public class MainActivity extends AppCompatActivity {
private EventViewGroup evg;
private EventView ev;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
evgA= findViewById(R.id.evg);
evA= findViewById(R.id.ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("event", "----------->dispatchTouchEvent:::MainActivity----" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("event", "----------->onTouchEvent:::MainActivity----" + event.getAction());
return super.onTouchEvent(event);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.gerry.dispatchevent.viewgroup.EventViewGroup
android:id="@+id/evg"
android:layout_width="match_parent"
android:layout_height="500px"
android:layout_marginTop="250px"
android:background="@android:color/holo_green_dark"
android:gravity="center"
android:orientation="vertical">
<com.gerry.dispatchevent.view.EventView
android:id="@+id/ev"
android:layout_width="200px"
android:layout_height="150px"
android:background="@android:color/holo_blue_light" />
</com.gerry.dispatchevent.viewgroup.EventViewGroup>
</FrameLayout>
開始分析
0為按下動(dòng)作佛致,1為抬起動(dòng)作峻黍。
1. 對(duì)事件不進(jìn)行任何修改
- 觸摸Activity
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
結(jié)論:
在默認(rèn)情況下昨寞,Activity會(huì)把事件向下依次按照層級(jí)分發(fā)到觸摸的最后一個(gè)ViewGroup或者View糙臼,然后會(huì)執(zhí)行最后一個(gè)ViewGroup或者View的onTouchEvent()方法凑保,然后又向上依次按照層級(jí)去觸發(fā)onTouchEvent()事件敌完,中途若沒有被消費(fèi)徐裸,就會(huì)傳遞直到activity,整個(gè)流程呈U形刻撒,隧道式向下分發(fā)骨田,然后冒泡式向上處理。
2. 修改ViewGroup的dispatchTouchEvent方法声怔,返回false态贤。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
3. 修改View的dispatchTouchEvent方法,返回false醋火。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
4. 修改ViewGroup的dispatchTouchEvent方法悠汽,返回true箱吕。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
5. 修改View的dispatchTouchEvent方法,返回true柿冲。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
E/event: ----------->onInterceptTouchEvent:::ViewGroup----1
E/event: ----------->dispatchTouchEvent:::View----1
從2茬高,3,4假抄,5可以得出的結(jié)論:
- 當(dāng)dispatchTouchEvent返回false時(shí)怎栽,事件不會(huì)繼續(xù)往下分發(fā),無論是ViewGroup還是View宿饱,都會(huì)從上一級(jí)的onTouchEvent事件向上傳遞熏瞄,不會(huì)執(zhí)行自己的onTouchEvent()方法
- 當(dāng)dispatchTouchEvent返回true時(shí),表示事件直接被消費(fèi)谬以,這個(gè)事件也就停止分發(fā)且不會(huì)逆向向上傳遞强饮,直接結(jié)束了。
- 返回super:事件將會(huì)繼續(xù)向下分發(fā)为黎,直到事件被消費(fèi)為止邮丰。
6. 修改ViewGroup的onInterceptTouchEvent方法,返回false铭乾。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
7. 修改ViewGroup的onInterceptTouchEvent方法柠座,返回true。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
從6片橡,7可以得出的結(jié)論:
- 當(dāng)onInterceptTouchEvnt返回false/super(默認(rèn))時(shí)妈经,事件將會(huì)正常向下分發(fā),分發(fā)至下級(jí)的dispatchTouchEvent方法 再次判斷是否分發(fā)事件捧书。
- 當(dāng)onInterceptTouchEvent返回true時(shí)吹泡,表示ViewGroup容器攔截后續(xù)事件,會(huì)執(zhí)行該ViewGroup的onTouchEvent()方法然后停止向下分發(fā)轉(zhuǎn)而通過onTouchEvent()向上傳遞经瓷,直到最終被消費(fèi)
8. 修改ViewGroup的onTouchEvent方法求橄,返回false隘马。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
9. 修改ViewGroup的onTouchEvent方法素邪,返回true庐舟。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
E/event: ----------->onTouchEvent:::ViewGroup----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
E/event: ----------->onTouchEvent:::ViewGroup----1
10. 修改View的onTouchEvent方法,返回false色冀。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
11. 修改View的onTouchEvent方法潭袱,返回true。
- 觸摸ViewGroup
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::ViewGroup----0
E/event: ----------->onTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->onTouchEvent:::MainActivity----1
- 觸摸View
E/event: ----------->dispatchTouchEvent:::MainActivity----0
E/event: ----------->dispatchTouchEvent:::ViewGroup----0
E/event: ----------->onInterceptTouchEvent:::ViewGroup----0
E/event: ----------->dispatchTouchEvent:::View----0
E/event: ----------->onTouchEvent:::View----0
E/event: ----------->dispatchTouchEvent:::MainActivity----1
E/event: ----------->dispatchTouchEvent:::ViewGroup----1
E/event: ----------->onInterceptTouchEvent:::ViewGroup----1
E/event: ----------->dispatchTouchEvent:::View----1
E/event: ----------->onTouchEvent:::View----1
從8锋恬,9屯换,10,11可以得出的結(jié)論:
- 當(dāng)onTouchEvent返回false/super(默認(rèn))時(shí),不消費(fèi)掉此次事件彤悔,事件將會(huì)層層向上傳遞嘉抓,直到被消費(fèi)。
- 當(dāng)onTouchEvent返回true時(shí)晕窑,立即消費(fèi)掉事件抑片,事件將不會(huì)向上傳遞,事件到此終止杨赤。
最終結(jié)論
dispatchTouchEvent 分發(fā)
- 當(dāng)dispatchTouchEvent返回false時(shí)敞斋,事件不會(huì)繼續(xù)往下分發(fā),無論是ViewGroup還是View望拖,都會(huì)從上一級(jí)的onTouchEvent事件向上傳遞,不會(huì)執(zhí)行自己的onTouchEvent()方法
- 當(dāng)dispatchTouchEvent返回true時(shí)挫鸽,表示事件直接被消費(fèi)说敏,這個(gè)事件也就停止分發(fā)且不會(huì)逆向向上傳遞,直接結(jié)束了丢郊。
- 返回super:事件將會(huì)繼續(xù)向下分發(fā)盔沫,直到事件被消費(fèi)為止。
onInterceptTouchEvent 攔截
- 當(dāng)onInterceptTouchEvnt返回false/super(默認(rèn))時(shí)枫匾,事件將會(huì)正常向下分發(fā)架诞,分發(fā)至下級(jí)的dispatchTouchEvent方法 再次判斷是否分發(fā)事件。
- 當(dāng)onInterceptTouchEvent返回true時(shí)干茉,表示ViewGroup容器攔截后續(xù)事件谴忧,會(huì)執(zhí)行該ViewGroup的onTouchEvent()方法然后停止向下分發(fā)轉(zhuǎn)而通過onTouchEvent()向上傳遞,直到最終被消費(fèi)
onTouchEvent 消費(fèi)
- 當(dāng)onTouchEvent返回false/super(默認(rèn))時(shí)角虫,不消費(fèi)掉此次事件沾谓,事件將會(huì)層層向上傳遞,直到被消費(fèi)戳鹅。
- 當(dāng)onTouchEvent返回true時(shí)均驶,立即消費(fèi)掉事件,事件將不會(huì)向上傳遞枫虏,事件到此終止妇穴。
參考鏈接:
http://www.reibang.com/p/fc0590afb1bf
http://www.reibang.com/p/66a80ff0133b