看了N多文章介紹事件分發,不如自己寫一個例子更透徹。
知識點提要:
1.View 具有的方法:
dispatchTouchEvent(MotionEvent event);(分發)true—->消費
onTouchEvent(MotionEvent event);(觸摸)
2.ViewGroup 具有的方法:
dispatchTouchEvent(MotionEvent event);(分發)true—->消費
onTouchEvent(MotionEvent event);(觸摸)
onInterceptTouchEvent(MotionEvent ev);(攔截)
3.Activity具有的方法:
dispatchTouchEvent(MotionEvent event);(分發)true—->消費
根據以上,上主要代碼:
MainActivity重寫onCreate 和dispatchTouchEvent:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.myRelativeLayout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "myRelativeLayout.onClick");
}
});
findViewById(R.id.myTextView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "myTextView.onClick");
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
MyRelativeLayout重寫onTouchEvent(),onInterceptTouchEvent(),dispatchTouchEvent()。
public class MyRelativeLayout extends RelativeLayout {
public String TAG = getClass().getName();
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent");
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
// return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
}
MyTextView 重寫dispatchTouchEvent(MotionEvent event),
onTouchEvent(MotionEvent event);
public class MyTextView extends TextView {
public String TAG = getClass().getName();
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
}
1.觸摸MyTextView:
MainActivity: dispatchTouchEvent–down
MyRelativeLayout:dispatchTouchEvent–down
MyRelativeLayout: onInterceptTouchEvent–down
MyTextView: dispatchTouchEvent–down
MyTextView: onTouchEvent–down
MainActivity: dispatchTouchEvent–up
MyRelativeLayout: dispatchTouchEvent–up
MyRelativeLayout: onInterceptTouchEvent–up
MyTextView: dispatchTouchEvent–up
MyTextView: onTouchEvent–up
MainActivity: myTextView.onClick
2.修改MyRelativeLayout onInterceptTouchEvent 傳回true結果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: myRelativeLayout.onClick
3.修改MyRelativeLayout dispatchTouchEvent傳回true結果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
4.修改MyTextView dispatchTouchEvent傳回true結果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent
5.修改MyRelativeLayout dispatchTouchEvent傳回false結果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MainActivity: dispatchTouchEvent
6.修改MyTextView dispatchTouchEvent傳回false結果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: myRelativeLayout.onClick
對比1和2,結論一:父View的onInterceptTouchEvent 傳回true則touch不會再傳遞給子View,該事件由父View處理。
對比1和3、4,結論二:父View的dispatchTouchEvent 傳回true,則touch不會再往下傳遞,up事件和down事件一樣,父View接收up事件。
對比1和3、5,結論三:父View的dispatchTouchEvent 傳回false,則touch不會再往下傳遞,up事件也不會再交給該父View處理。
對比1和3、5、6,結論四:子View的dispatchTouchEvent 傳回false,則touch不會再往下傳遞,up事件也不會交給該子View處理,該事件交給父View處理,且不會up事件傳遞不會調用該父View的onInterceptTouchEvent 事件。
對比1和2、6、結論五:父View的onInterceptTouchEvent 傳回true和子View的dispatchTouchEvent 傳回false效果類似,差別隻在于後者會執行一次dispatchTouchEvent 事件。
對比1和4、6,結論六:子View的dispatchTouchEvent傳回true和false差別:傳回true,不會執行父View的onTouchEvent方法,up事件父View會執行onInterceptTouchEvent事件;傳回false,會執行父View的onTouchEvent方法,up事件父View不會執行onInterceptTouchEvent事件。
結論不太好記,
總結一下就是,父dispatchTouchEvent 傳回false ,事件不會傳遞給子View,該事件會被父View的父View來處理調用onTouchEvent方法;
子View dispatchTouchEvent 傳回true,該事件會被丢棄,不會調用onTouchEvent方法,touch事件會被丢棄,想繼續傳遞應該傳回super.dispatchTouchEvent ;
父View 調用onInterceptTouchEvent 子View不會接受到該事件,由該父View處理,up事件不會受到影響。