今天,看了顾浩鑫的Android高级进阶这本书,了解了Activity、View、ViewGroup的事件传递机制,一次完整的事件传递主要包括三个阶段:事件的分发(dispatch)、拦截(Intercept)和消费(Consume)。
package com.asce1885.viewdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
/**
* Created by guhaoxin on 16/3/28.
*/
public class MyRelativeLayout extends RelativeLayout {
private static final String TAG = "MyRelativeLayout";
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "dispatchTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
//拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "onTouchEvent ACTION_CANCEL");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
package com.asce1885.viewdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
/**
* Created by guhaoxin on 16/3/28.
*/
public class MyRelativeLayout extends RelativeLayout {
private static final String TAG = "MyRelativeLayout";
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "dispatchTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
//拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "onTouchEvent ACTION_CANCEL");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
package com.asce1885.viewdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
/**
* Created by guhaoxin on 16/3/28.
*/
public class MyTextView extends TextView {
private static final String TAG = "MyTextView";
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "dispatchTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
break;
default:
break;
}
Log.e(TAG, String.valueOf(super.dispatchTouchEvent(ev)));
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onTouchEvent ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.e(TAG, "onTouchEvent ACTION_CANCEL");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
我们可以得出如下结论:
(1)触摸事件的传递顺序是由Activity到ViewGroup,再由ViewGroup递归传递给它的子View;
(2)ViewGroup通过onInterceptTouchEvent方法对事件进行拦截,如果该方法返回true,则事件不会向下传递,如果返回false或super.onInterceptTouchEvent,则事件会继续传递子View。
(3)在子View对事件进行消费后,ViewGroup将接收不到任何事件。
代码中Log.e(TAG, String.valueOf(super.dispatchTouchEvent(ev)));打印出结果为true,事件停止