美文网首页
Android事件分发学习路线

Android事件分发学习路线

作者: 贝贝ovo | 来源:发表于2019-04-02 13:16 被阅读0次

总结:

1.事件分发过程由三个方法协助完成

  • dispatchTouchEvent() //分配
  • onInterceptTouchEvent() //拦截
  • onTouchEvent() //处理
    //三者的关系(伪代码)
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if(onInterceptTouchEvent(ev)){
            consume = onTouchEvent(ev);
        }else {
            consume = child.dispatchTouchEvent(ev);
        }
        return consume;
    }

2.事件分发顺序:

Activity(Window) -> ViewGroup -> View

3.拦截事件

在事件分发三大类(Activity、ViewGroup、View)中,Activity和View不会去拦截事件(也就是不能重写onInterceptTouchEvent()方法)

4.事件分发路线呈U型

groupA 包 groupB 包 viewB,全部super调用不拦截,日志如下(看图解那篇)

--------------dispatchTouchEvent--------------EventActivity
--------------dispatchTouchEvent--------------groupA
--------------onInterceptTouchEvent--------------groupA
--------------dispatchTouchEvent--------------groupB
--------------onInterceptTouchEvent--------------groupB
--------------dispatchTouchEvent--------------viewB
--------------onTouchEvent--------------viewB
--------------onTouchEvent--------------groupB
--------------onTouchEvent--------------groupA
--------------onTouchEvent--------------EventActivity

5.理解dispatchTouchEvent(是否分发或传递事件)

  • 返回false不再向下分发,无论是ViewGroup还是View,都会从该View的上一级的onTouchEvent事件向上传递
    ( 注意:当一个View不在向下分发时(dispatchTouchEvent),不会执行自己的onTouchEvent()的,拦截时(onInterceptTouchEvent) 会执行onTouchEvent())

  • 返回true:表示事件直接被消费,这个事件也就停止分发且不会逆向向上传递,直接结束了。

  • 返回super:事件将会继续向下分发,直到事件被消费为止。

6.理解onInterceptTouchEvent(是否拦截该事件,默认不拦截)

  • 返回false(super默认false):此次不拦截,事件将会正常向下分发,分发至下级的dispatchTouchEvent方法 再次判断是否分发事件。

  • 返回true:拦截后续事件,会执行该View的onTouchEvent()方法然后停止向下分发转而通过onTouchEvent()向上传递,直到最终被消费

7. 理解onTouchEvent(是否消费掉此次事件)

首先,理解onTouchEvent方法的触发满足的条件,在正常流程下,我们提到过整个流程呈U形,U形的转折点就是从Activity开始事件向下分发到最后一个View或者ViewGroup的onTouchEvent()方法。

  • 返回true:立即消费掉事件,事件将不会向上传递,事件到此终止。
  • 返回false/super:不消费掉此次事件,事件将会层层向上传递,直到被消费。

8.理解事件消费

简而言之,onTouchEvent返回true就表示此次事件被消费掉

        findViewById(R.id.A).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

如果view设置了触摸事件,onTouch实现中

  • 返回true:立即消费掉事件,事件将不会向上传递,事件到此终止。
  • 返回false/super:不消费掉此次事件,事件将会层层向上传递,直到被消费。
事件分发U形图 Demo事件分发U形图

大总结

1.dispatchTouchEventonTouchEvent 一旦return true,事件就停止传递了(到达终点)(没有谁能再收到这个事件)。看上图中只要return true事件就没再继续传下去了,对于return true我们经常说事件被消费了,消费了的意思就是事件走到这里就是终点,不会往下传,没有谁能再收到这个事件了。

2.dispatchTouchEventonTouchEvent方法在return false的时候,事件都回传给父控件的onTouchEvent处理。

  • 对于dispatchTouchEvent返回false的含义应该是:事件停止往子View传递和分发同时开始往父控件回溯(父控件的onTouchEvent开始从下往上回传直到某个onTouchEvent return true),事件分发机制就像递归,return false 的意义就是递归停止然后开始回溯。
  • 对于onTouchEvent return false就比较简单了,它就是不消费事件,并让事件继续往父控件的方向从下往上流动。

3.onInterceptTouchEvent的作用
onInterceptTouchEvent方法中return true就会交给自己的onTouchEvent的处理,如果不拦截就是继续往子控件往下传。默认是不会去拦截的,因为子View也需要这个事件,所以onInterceptTouchEvent拦截器return super.onInterceptTouchEvent()return false是一样的,是不会拦截的,事件会继续往子ViewdispatchTouchEvent传递。

鸿洋两篇总结

1、View的事件转发流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent
dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent

2、ViewGroup

  • 如果ViewGroup找到了能够处理该事件的View,则直接交给子View处理,自己的onTouchEvent不会被触发;

  • 可以通过复写onInterceptTouchEvent(ev)方法,拦截子View的事件(即return true),把事件交给自己处理,则会执行自己对应的onTouchEvent方法

  • View可以通过调用getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup对其MOVE或者UP事件进行拦截;

Github地址

相关文章

网友评论

      本文标题:Android事件分发学习路线

      本文链接:https://www.haomeiwen.com/subject/rvwvbqtx.html