笔记之后整理一下
Viewpager 放一个listview
如果down事件没有处理 move事件也不处理? -- 针对叶子节点
在viewpager中重写onInterceptTouchEvent方法 对子view进行拦截
return true 的话
listview将不能滑动
return false的话
listview可以滑动 viewpager将不能滑动
对onInterceptTouchEvent()不重写就不会冲突 谷歌进行了处理
看下ViewGroup的dispatchTouchEvent分发流程
public boolean dispatchTouchEvent(MotionEvent ev) 在源码的2578行
第一个层级 总经理 viewgroup
第二个层级 总监 viewgroup
第三个层级 清洁工 view 处理事件
Down -- 只有一个
首先在 viewgroup的dispatchtouchevent中
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;
}
1.上面代码判断事件是否要拦截
2.不拦截就分发
代码2634 if (!canceled && !intercepted) { 分发
if (actionMasked == MotionEvent.ACTION_DOWN|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) ||actionMasked==MotionEvent.ACTION_HOVER_MOVE) {
分发
down事件才会分发
if (newTouchTarget == null && childrenCount != 0) 判断有没有子view buildTouchDispatchChildList对子view进行排序(根据z轴或者书写顺序 前面的优先响应)
for (int i = childrenCount - 1; i >= 0; i--) { final int childIndex = getAndVerifyPreorderedIndex( childrenCount, i, customOrder); for循环倒序取出child
if (!child.canReceivePointerEvents()|| !isTransformedTouchPointInView(x, y, child, null)) 判断取出的child是否能接收事件 1.visible 2.child.animation 第二个判断是要在能够响应的范围内
假如child可以处理该事件就走 不能处理就for继续走
接下来又调用了 if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign))分发处理事件 将child传入
因为child不为null 执行 dispatchTransformedTouchEvent中的 handled = child.dispatchTouchEvent(transformedEvent);方法 假如child是viewgroup 就会递归调用
如果 dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign) 返回值为true 就会执行
newTouchTarget = addTouchTarget(child, idBitsToAssign);
private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {
final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
}
对newTouchTarget进行赋值
三个条件
target.next = mFirstTouchTarget = null
newTouchTarget = mFirstTouchTarget = TouchTarget.obtain(child, pointerIdBits)
alreadyDispatchedToNewTouchTarget = true;
接着又往下
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) { 因为上面的赋值 while只会执行一次
final TouchTarget next = target.next;
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { //这两个条件判断均为ture
handled = true; //会执行 子child处理了 就不处理了
} 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;
}
}
3.分发或者处理
1.拦截(相当于你是最后一个,事件到底处不处理(全部不处理和拦截一样))
handled = dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS);(是否处理)
handled为ture 就代表处理 就不分发了 自己处理了
里面child为null的话就到view的dispatchTouchEvent();看是onTouch还是onClick
3.不拦截 走else