自定义下拉刷新组件之前,必须要了解什么是事件分发机制。
按照顺序阅读,看完郭霖 事件分发机制上,郭霖 事件分发机制下,和鸿洋 事件分发机制上,鸿洋 事件分发机制下以后结合Android开发艺术探索和源码,然后看事件分发机制总结这篇,基本能够掌握事件分发机制了。
事件分发机制的内容对于初学者而言,是反复看,实践过后再理解便能掌握其原理。下面我们简要介绍下事件分发机制,具体内容,请按顺序反复阅读上面提及的几篇文章。
事件分发机制
什么是事件分发机制?
事件分发机制就是,当一个点击事件发生后,系统将这个事件按照Activity,ViewGroup,View传递给具体的View去处理。
事件分发机制涉及以下三个方法
- dispatchTouchEvent 分发点击事件
- onInterceptTouchEvent 拦截点击事件
- onTouchEvent 处理点击事件
记住View没有onInterceptTouchEvent这个方法。
小例子
我们通过一个小例子来大致了解下事件分发机制的流程,这里我们使用系统默认的返回方式。
步骤:
1. 创建TestLinearLayout 继承 Linearlayout, 重写 dispatchTouchEvent, onInterceptTouchEvent,onTouchEvent
2. 创建TestButton 继承 Button,重写onInterceptTouchEvent,onTouchEvent
3. 创建布局
4. 重写Activity的dispatchTouchEvent,onTouchEvent
TestLinearLayout
public class TestLinearLayout extends LinearLayout {
public String TAG = "TestLinearLayout";
public TestLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onTouchEvent: ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "onTouchEvent: ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "onTouchEvent: ACTION_UP");
break;
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onInterceptTouchEvent: ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "onInterceptTouchEvent: ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "onInterceptTouchEvent: ACTION_UP");
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "dispatchTouchEvent: ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "dispatchTouchEvent: ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "dispatchTouchEvent: ACTION_UP");
break;
}
return super.dispatchTouchEvent(ev);
}
}
TestButton中的内容和TestLinearLayout完全一样,只是少了OnInterceptTouchEvent不贴了。
布局
<?xml version="1.0" encoding="utf-8"?>
<com.example.com.myapplication.test.TestLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.com.myapplication.TestButton
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.example.com.myapplication.test.TestLinearLayout>
在MainActivity中按类似的方式重写dispatchTouchEvent和OnTouchEvent。
点击空白处打印如下
通过这张图片我们可以看到事件确实是从Activity传递到ViewGroup,由于Activity没有OnInterceptTouchEvent,所以调用完dispatchTouchEvent后,调用ViewGroup的dispatchTouchEvent。
我们还可以发现ViewGroup的onTouchEvent 比Activity先调用。
点击Button打印如下
在这里我们可以清晰的看到
Activity 调用dispatchTouchEvent
ViewGroup 调用dispatchTouchEvent
ViewGroup 调用onInterceptTouchEvent
View 调用dispatchTouchEvent
VIew 调用onTouchEvent
此时我们看到了当View调用了onTouchEvent后,ViewGroup和MainActivity中的onTouchEvent不被调用。
这是为什么呢?
由于Button是可点击的,一旦触发了Bu