《Android开发艺术探索》--View事件分发

简介

分析Android中的事件体系其实就是分析MotionEvent对象的处理过程。即当一个事件序列产生之后,系统需要把这一系列的事件交给一个具体的View来进行处理,而传递的过程就是事件的分发。在这个过程中最重要的就是这三个方法:

  • public boolean dispatchTouchEvent(MotionEvent ev)
    用于事件的分发,如果事件能传递给当前的View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级dispatchTouchEvent方法的影响,表示是否消耗当前事件。

  • public boolean onInterceptTouchEvent(MotionEvent ev)
    用来判断是否拦截某个事件,如果View拦截了某个事件,那么在同一个事件序列中,此方法不会被再次调用。

  • public boolean onTouchEvent(MotionEvent ev)
    用于处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次收到事件。

以上的三个方法的关系可以用伪代码形象的表示:

public boolean dispatchTouchEvent(MotionEvent event) {
        boolean consume = false;

        if(onInterceptTouchEvent(event)){//当前的View拦截该事件
            consume = onTouchEvent(event);//当前事件调用onTouchEvent来处理事件
        }else{//当前View不拦截该事件,将事件交给下一级的dispatchTouchEvent()
            consume = child.dispatchTouchEvent(event);
        }
        return consume;
    }

上边的伪代码形象的表示了事件处理的流程。

事件传递和处理:

产生点击事件之后的传递过程:

Activity->Window->ViewGroup->…..->View

事件的分发:

  • 首先传递给根ViewGroup,他会调用自己的dispatchTouchEvent方法来进行事件的分发:

    • 在根ViewGroup的dispatchTouchEvent方法中首先调用onInterceptTouchEvent方法判断是否拦截该事件:

      • 若onInterceptTouchEvent方法返回true,表示当前的根ViewGroup要拦截该事件,则事件交给该ViewGroup的onTouchEvent方法来处理

      • 若onInterceptTouchEvent方法返回false,表示当前的根ViewGroup不拦截该事件,则事件交给根ViewGroup的下一级ViewGroup

  • 下一级ViewGroup也是同样调用自己的dispatchTouchEvent方法进行事件的分发,直到事件最终被处理。

View处理事件的流程:
当一个View要处理具体事件时,也是按照一定层次顺序进行处理的。

  • 如果该View设置了OnTouchListener,那么OnTouchListener中的onTouch方法会被回调:

    • 若onTouch方法返回true,则该View的onTouchEvent方法就不会被调用

    • 若onTouch方法返回false,则该View的onTouchEvent方法就会被调用

  • 若该View的onTouchEvent方法被调用,若是设置了onClickListener,则调用其中的onClick方法,也就是我们平时常用的onClic方法

所以事件处理时候调用顺序就是:

onTouch->onTouchEvent->onClick

若所有的View的onTouchEvent都返回了false,则事件会一层一层的向上返回,最终会交给Activity来处理,Activity的onTouchEvent方法会被调用。

总结:

  1. 一个事件序列是从ACTION_DOWN开始,一直到ACTION_UP为止的中间一系列的操作的序列

  2. 正常情况下一个事件序列只能被一个View拦截并消耗,因为当一个事件拦截了ACTION_DOWM事件之后,同一个事件序列就会直接交给他处理,而不会再次调用其onInterceptTouchEvent方法来判断是否拦截。

  3. ViewGrou默认不拦截任何事件,其onInterceptTouchEvent方法默认返回false

  4. View没有onInterceptTouchEvent方法,一旦有事件传递给他,那么就会调用他的onTouchEvent方法

  5. View的onTouchEvent默认是消耗事件的,除非是不可点击状态(clickable和longClickable同时为false)

  6. View的enable属性不影响view的点击事件,即使是不可见的状态,也能响应点击事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值