深入解析Andoird应用开发中View的事件传递

2019-12-10 19:11:30于丽

上面代码中的Attention在后面部分将会涉及,重点注意。

这里需要指出一点的是,一系列动作中的不同Pointer可以分配给不同的View去响应。ViewGroup会维护一个PointerId和处理View的列表TouchTarget,一个TouchTarget代表一个可以处理Pointer的子View,当然一个View可以处理多个Pointer,比如两根手指都在某一个子View区域。TouchTarget内部使用一个int来存储它能处理的PointerId,一个int32位,这也就是上层为啥最多只能允许同时最多32点触碰。

看一下Attention 3 处的代码,我们经常说view的dispatchTouchEvent如果返回false,那么它就不能系列动作后面的动作,这是为啥呢?因为Attention 3处如果返回false,那么它不会被记录到TouchTarget中,ViewGroup认为你没有能力处理这个事件。

这里可以看到,ViewGroup真正处理事件是在dispatchTransformedTouchEvent里面,跟进去看看:

dispatchTransformedTouchEvent
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
    View child, int desiredPointerIdBits) {

   //没有子类处理,那么交给viewgroup处理
  if (child == null) {
    handled = super.dispatchTouchEvent(transformedEvent);
  } else {
    final float offsetX = mScrollX - child.mLeft;
    final float offsetY = mScrollY - child.mTop;
    transformedEvent.offsetLocation(offsetX, offsetY);
    if (! child.hasIdentityMatrix()) {
      transformedEvent.transform(child.getInverseMatrix());
    }

    handled = child.dispatchTouchEvent(transformedEvent);
  }
  return handled;
}

可以看到这里不管怎么样,都会调用View的dispatchTouchEvent,这是真正处理这一次点击事件的地方。

dispatchTouchEvent
  public boolean dispatchTouchEvent(MotionEvent event) {
    if (onFilterTouchEventForSecurity(event)) {
    //先走View的onTouch事件,如果onTouch返回True
    ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnTouchListener != null
        && (mViewFlags & ENABLED_MASK) == ENABLED
        && li.mOnTouchListener.onTouch(this, event)) {
      result = true;
    }

    if (!result && onTouchEvent(event)) {
      result = true;
    }
  }
    return result;
  }