事件分发机制总结

引用: https://developer.android.com/training/gestures/viewgroup.html

对ViewGroup和它的子View来说,触摸事件的处理方式是不一样的。可以通过重载View Group的 onInterceptTouchEvent() 方法,来确保ViewGroup及各个子View能正确相应触摸事件。

ViewGroup拦截触摸事件

不管是触摸ViewGroup或它的子View,onInterceptTouchEvent()方法都会调用。该方法返回true, 则子View收不到Touch Event,执行ViewGroup的 onTouchEvent()。 如果返回false,则向子控件传递,调用相应的子View的 onTouchEvent()方法。

 public class MyViewGroup extends ViewGroup {

  private int mTouchSlop;

  ...

  ViewConfiguration vc = ViewConfiguration.get(view.getContext());
mTouchSlop = vc.getScaledTouchSlop();

  ...

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    /*
     * 此方法判断是否需要拦截触摸事件,如果是滑动操作,则返回true,运行本类的 onTouchEvent。
     */

    final int action = MotionEventCompat.getActionMasked(ev);

    // 先处理触摸完成的情况
    if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
        // Release the scroll.
        mIsScrolling = false;
        return false; // 不拦截Touch Event,让子View 处理
    }

    switch (action) {
        case MotionEvent.ACTION_MOVE: {
            if (mIsScrolling) {
                // 如果正在滑动,则拦截Touch Event
                return true;
            }

            // 判断手指横向移动超过一定距离,则开始滚动

            // 需要读者自己实现 :)
            final int xDiff = calculateDistanceX(ev);

            // Touch slop should be calculated using ViewConfiguration
            // constants.
            if (xDiff > mTouchSlop) {
                // 开始滚动!
                mIsScrolling = true;
                return true;
            }
            break;
        }
        ...
    }

    // 通常情况下不拦截Touch Event,让子View来处理
    return false;
}

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
      // 这里我们开始处理touch event (e.g. 如果action是ACTION_MOVE,滚动container)。intercepted in
      // 这个方法只有在touch event在onInterceptTouchEvent中被截获时调用
      ...
    }
}

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