美文网首页
View的事件分发机制笔记

View的事件分发机制笔记

作者: 拿头撞鸡 | 来源:发表于2016-06-01 10:16 被阅读57次

    了解事件分发机制之前,需要对view的点击MotionEvent进行学习。事件分发的就是各种点击事件,即产生了一个MotionEvent事件后,我们要将它传递给需要处理该事件的view。

    MotionEvent

    手指解除屏幕后所产生的一系列事件。我们经常使用的事件包括:

    • ACTION_DOWN
      手指刚接触屏幕
    • ACTION_MOVE
      手指在屏幕上移动
    • ACTION_UP
      手指从屏幕上松开的一瞬间

    一次手指触摸屏幕的行为会触发一系列点击事件

    • 点击屏幕后松开
      DOWN-->UP
    • 点击屏幕,滑动后松开
      DOWN-->MOVE-->..MOVE-->UP

    通过MotionEvent对象,我们可以获取当前事件的X,Y坐标,getX() getY()是获取相对于当前View左上角的坐标,getRawX() getRawY()返回相对于屏幕左上角的坐标。

    点击事件传递规则

    当产生点击事件,会由以下三个方法来进行分发

    • public boolean dispatchTouchEvent(MotionEvetn event)
      用来进行事件分发,如果事件能够传递到当前View,则此方法一定会被调用
    • public boolean onInterceptTouchEvent(MotionEvent event)
      用来判断是否拦截某个事件,当前View拦截某个事件,则在同一个事件序列当中,此方法不会再被调用
    • public boolean onTouchEvent(MotionEvent event)
      处理点击事件,返回false交由父控件处理

    事件分发传递过程是由外向内的,也就是说当一个事件发生时,总是先传递给父元素,然后由父元素分发给子view
    伪代码如下:

    public boolean dispatchTouchEvent(MotionEvent event) {
        boolean consume = false;
        if ( onInterceptTouchEvent(event)) {
            consume = onTouchEvent(event);
        } else {
            consume = child.dispatchTouchEvent(event)
        }
    
        return consume;
    }
    

    当产生一个事件,首先会传递给根ViewGroup,它的dispatchTouchEvent就会被调用,如果它的onInterceptTouchEvent返回true,则表示该ViewGroup拦截此事件,它的onTouchEvent就会被调用,否则该事件传递给它的子view,子view的dispatchTouchEvent被调用,继续分发事件,知道该事件被处理。

    如果一个view设置了onTouchListener,那么onTouchListener中的onTouch会被回调。若onTouch返回false,当前view的onTouchEvent会被调用,否则,onTouchEvent则不会被调用。view设置onTouchListener比onTouchEvent优先级高。如果设置了onClickListener,onClick方法会被调用,但是优先级最低,处于事件传递的尾端。

    当一个事件发生,传递顺序为:Activity--Window--View。如果传递过程中没有任何一个view处理事件,即onTouchEvent返回false,则交由最终的父控件Activity处理,即Activity的onTouchEvent会被调用。我们可以这样理解,就是上层领导交代了一件事给下级部门经理处理,部门经理由交给了普通员工,若是普通员工说这事我搞不定,那只能部门经理处理,若是部门经理也搞不定,那只有上层领导来出面解决。

    注意

    1. view一旦决定拦截,那么这个事件序列都由它处理,且onInterceptEvent不在被调用。
    2. view一旦处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent中返回false),那么同一事件序列的后续事件也不会交由它处理。事件将交由父控件处理,这也和前文说明的一样,onTouchEvent返回false,由父控件处理。一旦事件由view处理,则它必须消耗这个事件,即onTouchEvent中返回true
    3. 如果view不消耗任何事件(除ACTION_DOWN),则这个事件序列会消失,且父元素的onTouchEvent也不会被调用,当前view可以持续受到后续事件,消失的事件最终交由Activity处理。

    相关文章

      网友评论

          本文标题:View的事件分发机制笔记

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