文章共分两篇,会详细介绍Activity,View,ViewGroup三者的触摸事件传递机制。一次完整的事件传递主要包括三个阶段,分别是事件的分发,拦截和消费。
1.1 触摸事件的类型
触摸事件对应的MotionEvent类,事件的类型主要有如下三种
ACTION_DOWN:用户手指按下的操作,一个按下标志着一个触摸事件的开始。
ACTION_MOVE:用户手指按下在抬起之前,移动的距离超过一定的值,会被判定为 ACTION_MOVE操作 一般手,指的轻微移动都会触发一系列的移动事件。
ACTION_UP:用户手指离开屏幕的操作,一次抬起操作标志着一次触摸事件的结束。
1.2 事件传递的三个阶段
分发(Dispatch):事件的分发对应这dispatchTouchEvent方法,在Android系统中所有的触摸事件都是通过这个方法分发的。
拦截(Intercept):事件的拦截对应着onInterceptTouchEvent方法,这个方法只在ViewGroup及其子类中存在。
消费(Consume):事件的消费对应着onTouchEvent方法。
在Android系统中,拥有事件传递能力的类有以下三种:
Activity:拥有dispatchTouchEvent和onTouchEvent两个方法。
ViewGroup:拥有dispatchTouchEvent,onInterceptTouchEvent和onTouchEvent两个方法。
View:拥有dispatchTouchEvent和onTouchEvent两个方法。
1.3 View事件的传递机制
这里所说的View指ViewGroup以外的View,如TextView,Button,ImageView等。
public class MyTextView extends AppCompatTextView {
private static final String TAG = MyTextView.class.getSimpleName();
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 dispatchTouchEvent(MotionEvent event) {
switch (event.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;
default:
break;
}
return super.dispatchTouchEvent(event);
}
@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;
default:
break;
}
return super.onTouchEvent(event);
}
}
同时定义MainActivity用来展示MyTextView,在这个Activity中,我们对MyTextView设置了点击(onClick)触摸(onTouch)监听。
public class MainActivity extends AppCompatActivity implements View.OnTouchListener , View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tv);
textView.setOnTouchListener(this);
textView.setOnClickListener(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.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;
default:
break;
}
return super.dispatchTouchEvent(event);
}
@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;
default:
break;
}
return super.onTouchEvent(event);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG,"MyTextView onTouch ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"MyTextView onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,"MyTextView onTouchEvent ACTION_UP");
break;
default:
break;
}
return false;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.tv) {
Log.e(TAG,"MyTextView onClick");
}
}
}
运行上面的代码,点击MyTextView,打印日志。
2019-10-29 16:26:55.547 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MyTextView: dispatchTouchEvent ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onTouch ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MyTextView: onTouchEvent ACTION_DOWN
2019-10-29 16:26:55.566 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTIO
2019-10-29 16:26:55.645 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MyTextView: dispatchTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MyTextView: onTouchEvent ACTION_UP
2019-10-29 16:26:55.648 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onClick
不同的返回方式传递流程相差甚远,请看流程图