事件分发学习笔记一(View篇)

附上学习地址http://blog.csdn.net/guolin_blog/article/details/9097463/

代码都是只考虑了最简单的情况,最简单的情况有利于搞懂机制

我用的是android 24的源码,与郭神的有一点出入,大概看看就好

单独分析View,不考虑ViewGroup

1.一个view的事件产生之后会首先调用dispatchTouchEvent方法,决定是否分发该事件

View#dispatchTouchEvent方法:

//返回true表示该View 处理这个事件 否则false
 public boolean dispatchTouchEvent(MotionEvent event) {

        boolean result = false;


        if (onFilterTouchEventForSecurity(event)) {


            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {//如果注册了onTouch事件,前两个条件满足,第三个条件表示是否为enable,第四个条件会执行onTouch方法,它也是最后一个条件,他的返回值决定了该view是否处理事件(由于一个事件产生后会先调用dispatchTouchEvent,然后我们分析得onTouch方法优先级挺高的,毕竟现在还没有看到onClick方法,这里的onTouch就是注册touch事件的时候我们实现的那个方法)
                result = true;
            }
//如果上面的条件没有满足,那么就会执行View#onTouchEvent方法
            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }


        return result;
    }

2.如果上面的dispatchTouchEvent在onTouch中就返回了true,那么就结束了,如果没有,就会继续向下执行如上代码,执行View#onTouchEvent(猜想onClick那些会在这里)

View#onTouchEvent

//返回true表示处理的事件,否则return false。 同时它return false则表示dispatchTouchEvent返回了false,它返回true表示dispatchTouchEvent返回了true
 public boolean onTouchEvent(MotionEvent event) {

        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {//view有click或者longClick,进入下面代码,否则return false(全部源码还有一些别的判断,这里不考虑)
            switch (action) {
                case MotionEvent.ACTION_UP:
                   performClick();//抬起手指,执行点击(该方法就是判断是否实现了onClick事件,然后调用它)
                    break;

                case MotionEvent.ACTION_DOWN:

                    break;

                case MotionEvent.ACTION_CANCEL:

                    break;

                case MotionEvent.ACTION_MOVE:

                    break;
            }

            return true;
        }

        return false;
    }

onTouchEvent里面就是如果有点击事件,并且可以点击(setOnClickListener()方法里面设置了clickable为true),当action为up的时候,就执行点击。并且只要有点击事件,就返回true,否则返回false。
注意:down->move->…->move->up 这是一个事件序列,只要有一个返回了false,后面的就不会被接收到。 但是尽管我们在onTouch中返回了false,但是会在onTouchEvent中如果有点击事件,会进入到switch那段代码,最后返回的还是false。所以button注册了ontouch事件后,一直可以收到action,因为他有clickable,但是imageview默认不可点击,所以在onTouchEvent中不会进入switch那块,最后返回了fasle;
换种说话就是,如果onTouch中返回了true,表示该view要处理这一串事件,所以他可以一直接受到,如果返回了false,表示在onTouch中view没说要处理,但是如果他是可点击的,在接下来的onTouchEvent中,view表明要处理这一串序列了,所以依旧可以接收到,但是imageview是不可点击的,所以他依旧返回false,这样dispatchTouchEvent就返回了false,所以事件就会开始分发。


copy一下郭神的问答:
onTouch和onTouchEvent有什么区别,又该如何使用?
从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

另外需要注意的是,onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值