Android 事件分发机制

过程

  1. 事件产生后,传递过程:Activity -> Window -> View
  2. 事件分发流程:
    在dispatchTouchEvent中进行分发,调用onInterceptTouchEvent判断是否拦截,拦截则调用onTouchEvent处理,不拦截则分发给子View处理,返回结果表示是否消耗事件
public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean consume = false;    //是否消耗事件
    if (onInterceptTouchEvent(ev)) {    //拦截事件,当前View来处理
        if(mTouchListener != null) {    //如果设置了TouchListener
            consume = mTouchListener.onTouch(ev);
        }
        if(!consume){   //未设置ToucheListener或者TouchListener.onTouch返回false才调用onTouchEvent
            consume = onTouchEvent(ev);
        }
    } else { //不拦截,分发给子View处理
       consume = child.dispatchTouchEvent(ev);
    }
    return consume
}

核心方法

  1. dispatchTouchEvent
    用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。
  2. onInterceptTouchEvent
    用来判断是否拦截某个事件,如果当前View拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
  3. onTouchEvent
    用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。

滑动冲突处理

内部拦截

通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外。

   public boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
                parent.requestDisallowInterceptTouchEvent(true);
                break;
        }
        case MotionEvent.ACTION_MOVE: {
                int deltaX = x -mLastX;
                int deltaY = y -mLastY;
                if (父容器需要此类点击事件)) {
                        parent.requestDisallowInterceptTouchEvent(false);
                }
                break;
        }
        case MotionEvent.ACTION_UP: {
                break;
        }
        default:
                break;
        }
        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }

外部拦截

由父容器判断是否需要拦截

 public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
                intercepted = false;
                break;
        }
        case MotionEvent.ACTION_MOVE: {
                if (父容器需要当前点击事件) {
                        intercepted = true;
                } else {
                        intercepted = false;
                }
               break;
        }
        case MotionEvent.ACTION_UP: {
                intercepted = false;
                break;
        }
        default:
                break;
        }
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

你可能感兴趣的:(Android 事件分发机制)