美文网首页android事件分发
3. View的事件分发机制(p143 第五点)

3. View的事件分发机制(p143 第五点)

作者: 真胖大海 | 来源:发表于2017-10-07 17:15 被阅读6次

这是学习《android开发艺术探究》的笔记 如果有什么不对的地方,欢迎指出。

1.验证P143第五点

如果View不消耗ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件 ,最终这些消失的点击事件会传递给Activity

情景 1. onInterceptTouchEvent始终拦截事件,onTouchEvent消耗ACTION_DOWN事件,不消耗其他事件

public class MyViewGroup extends FrameLayout {
 private static final String TAG = "MyViewGroup";

 public MyViewGroup(@NonNull Context context) {
     super(context);
 }

 public MyViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
     super(context, attrs);
 }

 public MyViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
     super(context, attrs, defStyleAttr);
 }


 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
     int action = ev.getAction();
     String ActionStr = Util.getActionStr(action);
     boolean consume;
     consume = true;
     Log.i(TAG, "onInterceptTouchEvent"+(consume?"拦截":"不拦截") + ActionStr);
     return consume;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
     int action = event.getAction();
     String ActionStr = Util.getActionStr(action);
     boolean consume;
     if (action == MotionEvent.ACTION_DOWN) {
         consume = true;
     } else {
         consume = false;
     }
     Log.i(TAG, "dispatchTouchEvent"+(consume?"消耗":"不消耗") + ActionStr);
     return consume;
 }
}

结果:当前View可以持续收到后续的事件

onInterceptTouchEvent拦截ACTION_DOW
onTouchEventt消耗ACTION_DOWN
onTouchEvent不消耗ACTION_MOVE
onTouchEvent不消耗ACTION_MOVE
onTouchEvent不消耗ACTION_UP

2.源码分析

if (!canceled && !intercepted) {
 for(遍历child){
  if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                              newTouchTarget = addTouchTarget(child, idBitsToAssign);
                              break;
  }
 }
}ß

if (mFirstTouchTarget == null) {
  // No touch targets so treat this as an ordinary view.
  handled = dispatchTransformedTouchEvent(ev, canceled, null,
                      TouchTarget.ALL_POINTER_IDS);
} 
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
          View child, int desiredPointerIdBits) {
          if (child == null) {
              handled = super.dispatchTouchEvent(event);
          } else {
              handled = child.dispatchTouchEvent(event);
          }
}

2.1源码逻辑

因为child消耗了ACTION_DOWN事件,
所以

  1. dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)返回true,
  2. addTouchTarget将被调用导致mFirstTouchTarget!=null
  3. dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER,IDS)不会被调用,即"父元素的onTouchEvent并不会被调用"。

而且child会在viewGroup不拦截事件的前提下,持续受到事件
所以书中会说

(4)如果View不消耗ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件

相关文章

网友评论

    本文标题:3. View的事件分发机制(p143 第五点)

    本文链接:https://www.haomeiwen.com/subject/ntnjyxtx.html