View的事件分发

2017-02-23  本文已影响0人  YangGui

View的事件分发是指将MotionEvent分发到合适的View上的过程。
此过程由三个重要函数完成:

  1. public boolean diapatchTouchEvent(MotionEvent ev)
    事件的分发
    事件传递到当前View后触发.如果事件能传到View,此方法一定会被调用。
    返回结果受当前View的onTouchEvent和下级的dispatchTouchEvent方法影响,表示当前View是否消耗当前事件。
  1. public boolean onInterceptTouchEvent(MotionEvent ev)
    在diapatchTouchEvent方法内部调用,表示是否拦截某个事件。
    返回结果表示是否拦截当前事件。

  2. public boolean onTouchEvent(MotionEvent event)
    在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件。

  3. OnTouchListener
    OnTouchListener的优先级高于OnTouchEvent。如果给View设置了OnTouchListener,那么它的onTouch方法会先于onTouchEvent

  4. OnClickListener
    OnClickListener在OnTouchEvent里面调用。如果设置了OnClickListener,在OnTouchEvent里面会调用其onClick方法,因此OnClickListener的优先级最低。

6.事件传递的过程Activity ->Window->View

下面的伪代码概括了View事件分发的大致流程。

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

几点总结

  1. 某个View一旦决定拦截一个事件(onInterceptTouchEvent(ev)返回true),那么这个事件序列就只能由它处理,并且不会在调用其onInterceptTouchEvent

  2. 如果某个View开始处理事件,但它不消化ACTION_DOWN事件(onTouchEvent返回false),那么同一序列中的其他事件也不交给它处理,重新交由其父控件处理,父控件的onTouchEvent会被调用

  3. 如果View不消耗ACTION_DOWN以外的事件,那么这个事件会消失,且父控件的onTouchEvent也不会调用,消失的事件交个Activity处理

  4. ViewGroup默认不拦截任何事件,onInterceptTouchEvent默认返回false。

  5. View没有onInterceptTouchEvent方法,一旦点击事件传递过来,onTouchEvent方法就会被调用

6.View的onTouchEvent默认是消耗事件(返回ture),除非它被设为不可点击(clickable和longClickable都为false)。

  1. View的enable属性不影响onTouchEvent的默认返回值。
上一篇 下一篇

猜你喜欢

热点阅读