android viewgroup点击变色,android ViewGroup 事件分发

1、ViewGroup跟上一节View一样先看各种情况下的日志然后在根据日志情况来分析源码

1.1 在默认都存在的情况下日志

09-12 06:46:19.390 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 0

09-12 06:46:19.390 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 0

09-12 06:46:19.390 19085-19085/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 0

09-12 06:46:19.390 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:46:19.390 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 0

09-12 06:46:19.410 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 2

09-12 06:46:19.410 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 2

09-12 06:46:19.410 19085-19085/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 2

09-12 06:46:19.410 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:46:19.410 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 2

09-12 06:46:19.557 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 1

09-12 06:46:19.557 19085-19085/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 1

09-12 06:46:19.557 19085-19085/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 1

09-12 06:46:19.557 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:46:19.558 19085-19085/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 1

09-12 06:46:19.561 19085-19085/com.example.chao.viewontouch I/Tag: view -> onClick

1.2 这次是取消onClickListener情况下日志 取消了onClickListener 等于没有消费事件

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 0

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 0

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 0

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 0

09-12 06:44:39.744 17254-17254/com.example.chao.viewontouch I/Tag: ViewGroup -> onTouchEvent ->0

1.3 在view中的onTouchEvent 返回值为true

09-12 06:45:40.509 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 0

09-12 06:45:40.509 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 0

09-12 06:45:40.509 18253-18253/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 0

09-12 06:45:40.509 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:45:40.509 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 0

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 2

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 2

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 2

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 2

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 1

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 1

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> dispatchTouchEvent -> 1

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouch

09-12 06:45:40.690 18253-18253/com.example.chao.viewontouch I/Tag: view -> onTouchEvent -> 1

1.4 在ViewGroup中的onInterceptTouchEvent返回true

09-12 05:51:04.638 21669-21669/com.example.chao.viewontouch I/Tag: ViewGroup -> dispatchTouchEvent -> 0

09-12 05:51:04.638 21669-21669/com.example.chao.viewontouch I/Tag: ViewGroup -> onInterceptTouchEvent -> 0

09-12 05:51:04.638 21669-21669/com.example.chao.viewontouch I/Tag: ViewGroup -> onTouchEvent ->0

接下来第二节来通过源码解析为什么会出现这种情况

首先还是找到ViewGroup的dispatchTouchEvent(ev)

boolean handled = false dispatchTouchEvent 返回值

接下来看这段话 这段话就清除所有的状态 resetTouchState() mFirstTouchTarget 也是在里面置空 mFirstTouchTarget 下面会讲到

if (actionMasked == MotionEvent.ACTION_DOWN) {

// Throw away all previous state when starting a new touch gesture.

// The framework may have dropped the up or cancel event for the previous gesture

// due to an app switch, ANR, or some other state change.

cancelAndClearTouchTargets(ev);

resetTouchState();

}

以下这段代码比较重要 第一次按下的话 actionMasked == MotionEvent.ACTION_DOWN 这个肯定是down事件 所以一定会进入if判断

final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; 这段话就是判断子View有没有请求父控件不拦截 也就是这段 getParent().requestDisallowInterceptTouchEvent(true);

这里我们也没有调用这个方法 所以intercepted为false就是不拦截继续往下走

final boolean intercepted;

if (actionMasked == MotionEvent.ACTION_DOWN

|| mFirstTouchTarget != null) {

final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;

if (!disallowIntercept) {

intercepted = onInterceptTouchEvent(ev);

ev.setAction(action); // restore action in case it was changed

} else {

intercepted = false;

}

} else {

// There are no touch targets and this action is not an initial down

// so this view group continues to intercept touches.

intercepted = true;

}

接下来这段代码比较长 只取关键代码newTouchTarget = addTouchTarget(child, idBitsToAssign); addTouchTarget 这段对mFirstTouchTarget 和 newTouchTarget赋值

if (actionMasked == MotionEvent.ACTION_DOWN

|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)

|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {

....

.....

if (newTouchTarget == null && childrenCount != 0) {

....

....

newTouchTarget = addTouchTarget(child, idBitsToAssign);

}

}

整个ViewGroup事件分发的核心就这这下面的代码了

// Dispatch to touch targets.

if (mFirstTouchTarget == null) {

// No touch targets so treat this as an ordinary view.

handled = dispatchTransformedTouchEvent(ev, canceled, null,

TouchTarget.ALL_POINTER_IDS);

} else {

// Dispatch to touch targets, excluding the new touch target if we already

// dispatched to it. Cancel touch targets if necessary.

TouchTarget predecessor = null;

TouchTarget target = mFirstTouchTarget;

while (target != null) {

final TouchTarget next = target.next;

if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {

handled = true;

} else {

final boolean cancelChild = resetCancelNextUpFlag(target.child)

|| intercepted;

if (dispatchTransformedTouchEvent(ev, cancelChild,

target.child, target.pointerIdBits)) {

handled = true;

}

if (cancelChild) {

if (predecessor == null) {

mFirstTouchTarget = next;

} else {

predecessor.next = next;

}

target.recycle();

target = next;

continue;

}

}

predecessor = target;

target = next;

}

}

经过上面的分析 我们知道 mFirstTouchTarget 是不为空 所以走else的代码块 我们看到 if (dispatchTransformedTouchEvent(ev, cancelChild,target.child, target.pointerIdBits))这里面

只看一部分

if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {

event.setAction(MotionEvent.ACTION_CANCEL);

if (child == null) {

handled = super.dispatchTouchEvent(event);

} else {

handled = child.dispatchTouchEvent(event);

}

event.setAction(oldAction);

return handled;

}

如果说子 View 没有一个地方返回 true ,只会进来一次只会响应 DOWN 事件,代表不需要消费该事件,如果你想响应 MOVE,UP 必须找个地方ture对于ViewGroup来讲,如果你想拦截子 View 的 Touch 事件,可以覆写 onInterceptTouchEvent 返回 true 即可 , 如果说 onInterceptTouchEvent 返回的是 true 会执行该 ViewGroup 的 onTouchEvent 方法 , 如果子 View 没有消费 touch 事件也会调用该 ViewGroup 的 onTouchEvent 方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值