花了一下午的事件研究了一下android的事件分发机制,觉得有必要总结一下
顺便分享出来,希望对大家有用
1】首先最重要的是需要了解ViewGroup里面重写的三个方法
1)dispatchTouchEvent 用于事件的分发
2)onInterceptTouchEvent用于事件的拦截
3)onTouchEvent用于事件的处理
2】Android的事件分发是由上而下的,即从父类传递给子类,父View传递给子View
3】Android的事件处理是由下而上的,即从子类传递给父类,子View传递给父View
理解上面三点之后,再来分别看一下这三个方法
我们只需要知道每一个返回值对应的情况就能大致理解其作用了
1】dispatchTouchEvent方法
1)return falas
分为两种情况:
如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;
如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的 onTouchEvent 进行消费。
2)return true
事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递
3) return super.dispatchTouchEvent(ev)
事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法
2】onInterceptTouchEvent方法
1)return false
事件会被当前View放行,将传递给子View的dispatchTouchEvent方法
2)return true
事件被拦截,并且交给当前View的onTouchEvent去处理
3)return super.onInterceptTouchEvent
事件会被当前View放行,将传递给子View的dispatchTouchEvent方法
3】onTouchEvent方法
1)return false
事件会被传递给Activity或者父View的onTouchEvent处理,如果Activity或者父View的onTouchEvent也没有处理,则事件消失
2)return true
事件会被拦截给当前View的onTouchEvent处理
3)return super.onTouchEvent
事件会被传递给Activity或者父View的onTouchEvent处理,如果Activity或者父View的onTouchEvent也没有处理,则事件消失
画了一张图,来解释上面的文字描述
写了一个demo,可以自行更改每个方法的返回值来检测LOG
下面贴上代码,代码很简单
有一个Activity,一个SuperView,ChildView,TouchEventUtil用于打印日志
Activity:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.e("=================", "这是MainActivity的dispatchTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("=================", "这是MainActivity的onTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.onTouchEvent(event); } }
SuperView:
public class SuperView extends RelativeLayout { public SuperView(Context context) { super(context); } public SuperView(Context context, AttributeSet attrs) { super(context, attrs); } public SuperView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.e("=================", "这是SuperView的dispatchTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { Log.e("=================", "这是SuperView的onInterceptTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("=================", "这是SuperView的onTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.onTouchEvent(event); } }
ChildView:
public class ChildView extends LinearLayout { public ChildView(Context context) { super(context); } public ChildView(Context context, AttributeSet attrs) { super(context, attrs); } public ChildView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.e("=================", "这是ChildView的dispatchTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { Log.e("=================", "这是ChildView的onInterceptTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("=================", "这是ChildView的onTouchEvent" + TouchEventUtil.getTouchAction(event)); return super.onTouchEvent(event); } }