android 的事件分发

来源:互联网 发布:数据库中的字典表使用 编辑:程序博客网 时间:2024/06/05 19:50

文章为了学习android 的事件分发所用,记录过程会少许流水账。

2017/10/10

在事件分发中有三个关键的方法:
      dispatchTouchEvent() 
      onInterceptTouchEvent() 
      onTouchEvent() 

dispatchTouchEvent() 
      该方法是用来处理事件的分发。如果事件能够传递到当前View,那么一定会调用此方法。
onInterceptTouchEvent() 
      只在viewgroup中存在,是在dispatchTouchEvent中调用,来判断自己是否需要截取事件,如果该方法返回为true,那么View将消费该事件,即会调用onTouchEvent()方法。如果返回false,那么通过调用子View的dispatchTouchEvent()将事件交由子View来处理。
 onTouchEvent() 
    和onInterceptTouchEvent()一样也是在dispatchTouchEvent中调用的。用来处理点击事件,包括ACTION_DOWN,ACTION_MOVE,ACTION_UP。如果返回结果为false表示不消费该事件,并且也不会截获接下来的事件序列。如果返回为true表示当前View消费该事件。 
例如以下的布局,ViewGroup1嵌套ViewGroup2,ViewGroup2嵌套View。

当touch发生时,调用如下


注意:如果customView的onTouchEvent返回false,则回调其父布局的onTouchEvent,依次向上调用,直到返回true。
并且,当onInterceptTouchEvent返回true时,说明touch被拦截,则直接调用当前viewgroup的onTouchEvent,不在向下传递

本地打Log发现,当CustomView的onTouchEvent在处理action为ACTION_DOWN时返回false,则之后的touch action 不会下发到CustomView。

注:所有的dispatchEvent都是先从activity中开始,查看源码可以看到:
public booleandispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
   }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
   }
    return onTouchEvent(ev);
}

注意这行代码:if(getWindow().superDispatchTouchEvent(ev)) {
getWindow()获得的其实是PhoneWindow,DecorView是PhoneWindow的一个内部类,
查看PhoneWindow源码

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
}

可以看到,这里调用的既是DecorView的superDispatchTouchEvent
查看DecorView源码:
public booleansuperDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}

即调用viewGroup的dispatchTouchEvent,最终走的还是上述流程。

关键问题回答:

1.事件分发本质 

答:将点击事件(MotionEvent)向某个View进行传递并最终得到处理。即当一个点击事件发生后,系统需要将这个事件传递给一个具体的View去处理。这个事件传递的过程就是分发过程。

2.事件在哪些对象之前传递?

Activity、ViewGroup、View

一个点击事件产生后,传递顺序是:Activity(Window) -> ViewGroup -> View

原创粉丝点击