一、事件分發機制的基本概念
事件分發機制是指在Android系統中,當用戶對屏幕上的控件進行觸摸操作時,系統會依次把事件傳遞給控件樹上的每個View控件,直到有一個控件成功處理了該事件或者所有控件都未成功處理該事件。
Android的事件分發機制中涉及到三個重要的類:View、ViewGroup和 MotionEvent。View是控件的基類,ViewGroup是可以持有多個子View的View,而MotionEvent則是觸摸事件類。
事件分發機制的核心是ViewGroup.dispatchTouchEvent()方法和View.onTouchEvent()方法。前者是ViewGroup分發事件的方法,後者是View處理事件的方法。
二、事件分發機制的流程
事件分發機制的流程可以描述為:當用戶對屏幕進行觸摸操作後,系統會把該事件交給當前活動的Window對象。Window對象收到事件後會先交給DecorView進行處理。DecorView是Window對象的根View,它是一個FrameLayout,擁有多個子View,即Activity中設置的布局文件。接着DecorView會調用dispatchTouchEvent()方法把事件傳遞給子View,直到有一個子View成功處理了該事件。
當ViewGroup接收到事件時,會先調用自己的onInterceptTouchEvent()方法來詢問是否攔截該事件,如果該方法返回true,則表明該ViewGroup會處理該事件,否則就把該事件交給該ViewGroup的子View進行處理。如果所有的子View都不能處理該事件,則該事件繼續向上層的ViewGroup傳遞,直到確定該事件被處理或者整個控件樹中不存在可以處理該事件的View。
三、事件分發機制的代碼實現
public class MyViewGroup extends ViewGroup {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 對子View進行布局
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 進行事件分發
boolean handled = false;
if (onInterceptTouchEvent(ev)) {
handled = onTouchEvent(ev);
} else {
handled = getChildAt(0).dispatchTouchEvent(ev);
}
return handled;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 進行事件攔截
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 處理事件
return true;
}
}
四、事件分發機制的注意事項
1、onInterceptTouchEvent()方法可以攔截事件的傳遞,如果該方法返回true,則表明當前ViewGroup會處理該事件;
2、onTouchEvent()方法中必須要調用super.onTouchEvent()方法,否則子View將不會收到觸摸事件;
3、在Activity的布局中,可以使用android:onClick=””屬性來直接綁定點擊事件,也可以調用View的setOnClickListener()方法來動態綁定點擊事件;
4、在處理多點觸摸事件時,必須使用event.getActionMasked()來獲取事件類型,只有event.getAction()可能獲取不到正確的事件類型。
五、事件分發機制的優化
在事件分發機制中,每個View都要進行事件的分發和處理,如果View的層級結構非常複雜,那麼就會導致事件處理過程非常耗費系統資源。
針對這個問題,可以使用一些優化方式來加速事件的分發和處理,例如:
1、對於不需要接收觸摸事件的View,可以設置setClickable(false)或setFocusable(false),這樣可以避免不必要的事件分發;
2、在View的onTouchEvent()方法中,可以進行事件過濾,例如判斷點擊事件是否處於某個範圍內,避免不必要的事件處理;
3、在View的onTouchEvent()方法中,可以進行手勢識別,例如判斷是否有左滑或右滑的動作,從而在系統底層減少事件的發送。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/181847.html