欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android事件分发机制(绝对小白也能看懂)

程序员文章站 2024-03-20 15:12:22
...

最近在深入学习事件分发机制,一直被虐终于学有所成,特意把学后的总结记录下来,方便日后复习,也希望能帮助更多在事件分发上迷惑的人们。

首先你需要知道事件分发的对象有:Activity,Window,ViewGroup和View
其次你需要知道什么是事件流:ACTION_DOWN开始,数量不定的ACTION_MOVE和ACTION_UP组成了一个完整的事件流

如果以上两点你不知道,你可以先去学习下再来看这篇文章

這篇博客不按照市面上的那些套路来讲事件分发,直接上代码吓坏了读者,也不容易让读者理解,我们都从身边的事举例子延伸到代码中

  return (e = b = c = d = a = 3) == 3 ? true : false;

这条赋值语句很好懂,结果是返回true,能懂这一步你就知道了事件分发的核心思想(下面看下事件分发思想的伪代码)

  return (consume=Activity.disPatchTouchEvent(ev)= Window.disPatchTouchEvent(ev)
        = ViewGroup.disPatchTouchEvent(ev)= View.disPatchTouchEvent(ev))?true:false;

事件从Activity下发,一直到View结束,不断赋值,如果返回true此事件被消费了,返回false表示事件没有任何View消费

根据上面的伪代码我们可以得到如下结论:

1 每个事件分发的对象都有一个disPatchTouchEvent方法

2 如果其中一个disPatchTouchEvent返回true或者false,后面的disPatchTouchEvent就无效了(java代码里,常量不能被赋值也能和伪代码对应起来)

3 只有当disPatchTouchEvent未知的时候(super.dispatch)才可以继续往下传递形成一个完整的传递链

记住这个概念是很枯燥,那我们举个例子:

自定义ViewGroup  A里面有个Button B,重写A的disPatchTouchEvent方法直接返回true,重写B的disPatchTouchEvent方法输出“B是一个快乐的Button”,当我们点击B的时候会输出什么呢?

没错,什么也不会输出,如果你很容易懂了这一点我们就继续,如果没懂,请再把上面的结论思考一遍~

当我们在网上各种百度事件分发的时候总会告诉我们有三个方法:
disPatchTouchEvent,onInterceptTouchEvent,onTouchEvent
这三个方法都是做什么的呢?和事件分发有什么关系呢?下面我用最精炼的语言总结下:

disPatchTouchEvent:消费事件(true)/不消费事件(false)/分发事件(super)

onInterceptTouchEvent: 拦截事件(true)/不拦截事件(false 默认值)

onTouchEvent : 消费(true)/不消费(false)/ 根据View属性判断是否消费(super)

接下来看任玉刚大神ViewGroup的伪代码:

pulic boolean disPatchTouchEvent(MotionEvent ev){
   boolean consume=false;
   if(onInterceptTouchEvent(ev)){
     consume=onTouchEvent(ev);
   }else{
   consum=child.disPatchTouchEvent(ev)
   }
   return consume;
}

这段代码可以算是很精髓了,把ViewGroup到View的传递的本质描述的淋漓尽致

关于事件分发的补充:

1 只有ViewGroup有onInterceptTouchEvent方法,其他的没有

所以View的disPatchTouchEvent伪代码

pulic boolean disPatchTouchEvent(MotionEvent ev){
  return onTouchEvent(ev);

2 一旦事件在传递链上被消费,后续的对象就无法接收该事件(和核心事件分发的伪代码一致)

3 如果onTouchEvent(ev)返回false,那么将传递给上一级的onTouchEvent(ev)

这个怎么理解呢?

  return (consume=Activity.disPatchTouchEvent(ev)= Window.disPatchTouchEvent(ev)
        = ViewGroup.disPatchTouchEvent(ev)= View.disPatchTouchEvent(ev))?true:false;

disPatchTouchEvent里面再来一段伪代码

boolean consume=false;
        if(onInterceptTouchEvent(ev)){
            consume=onTouchEvent(ev);
        }else {
            if (child.disPatchTouchEvent(ev)) {
                consume = true;
            }else {
                onTouchEvent(ev);
            }
        }
        return consume;

Android事件分发机制(绝对小白也能看懂)