安卓事件分发从流程到情景分析

话不多说,整体时间分发的流程图附上:

带注释的代码如下: 由于事件分发这一块分支条件太多,所以必须结合情景来分析: 前提:父view viewpager,可左右滑动,子view listView, 可上下滑动。

情景1:父view onInterceptTouchEvent 为false。 结果:上下滑动可以,左右滑动不可以。 原因:父view设置了onInterceptTouchEvent为false后,down事件不会被父view拦截,事件传递到子view,mFirstTouchTarget != null,所以后续的move事件是子view处理,所以上下可以,左右不可以。

情景2:onInterceptTouchEvent 为false,ListView重写 dispatchTouchEvent 返回false 结果:左右可以,上下不可以 原因:down事件传递到子view后子view返回false,mFirstTouchTarget == null所以down事件最终由父view处理,后续move事件也由父view处理

情景4:手指点击到控件上后如果move到空白处,抬起手指后click事件不会触发。 原因:在view的onTouchEvent的move事件中:

scss 复制代码
if (!pointInView(x, y, touchSlop)) {
    // Outside button
    // Remove any future long press/tap checks
    removeTapCallback();
    removeLongPressCallback();
    if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
        setPressed(false);
    }
    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
}
ini 复制代码
if (pressed) {
    mPrivateFlags |= PFLAG_PRESSED;
} else {
    mPrivateFlags &= ~PFLAG_PRESSED;
}

如果移动到view外,会将mPrivateFlags & PFLAG_PRESSED置反,所以在up事件中:

scss 复制代码
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {

条件则不会满足,导致onClick不会触发。

情景5:前提:设ViewGroup VG中,有2个Button:A,B:3. 按下A,按下VG(空白区域),为什么先释放A,却无法触发A的点击事件,继续释放VG,又会触发A的点击事件。 原因:先释放A无法触发点击事件很好理解,因为此时是point_up事件,释放空白位置会触发的原因是:

csharp 复制代码
if (newTouchTarget == null && mFirstTouchTarget != null) {
    // Did not find a child to receive the event.
    // Assign the pointer to the least recently added target.
    newTouchTarget = mFirstTouchTarget;
    while (newTouchTarget.next != null) {
        newTouchTarget = newTouchTarget.next;
    }
    newTouchTarget.pointerIdBits |= idBitsToAssign;
}

在多指操作中,如果没有view处理某个时间,则把这个事件分发给target链表中的最后一个上,这样实际上虽然第二次按在了空白处,但up时间仍然是交给A处理,所以能够触发A的点击事件

情景6:按下VG(空白区域),为什么点击A,B无响应 原因: 按下空白区域由于没有子View处理该时间,所以mFirstTouchTarget为null

java 复制代码
if (actionMasked == MotionEvent.ACTION_DOWN
        || mFirstTouchTarget != null) {
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
        intercepted = onInterceptTouchEvent(ev);
        /// M : add log to help debugging
        if (intercepted == true && ViewDebugManager.DEBUG_TOUCH) {
            Log.d(TAG, "Touch event was intercepted event = " + ev
                    + ",this = " + this);
        }
        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;
}

这样intercepted会置为true,导致后续所有的事件都会被拦截。

相关推荐
发现一只大呆瓜9 小时前
虚拟列表:支持“向上加载”的历史消息(Vue 3 & React 双版本)
前端·javascript·面试
千寻girling10 小时前
Koa.js 教程 | 一份不可多得的 Node.js 的 Web 框架 Koa.js 教程
前端·后端·面试
程序员清风10 小时前
北京回长沙了,简单谈谈感受!
java·后端·面试
网络安全-杰克11 小时前
2026面试自动化测试面试题【含答案】
自动化测试·软件测试·面试·职场和发展
千寻girling14 小时前
主管:”人家 Node 框架都用 Nest.js 了 , 你怎么还在用 Express ?“
前端·后端·面试
xiaoxue..14 小时前
合并两个升序链表 与 合并k个升序链表
java·javascript·数据结构·链表·面试
猿小羽16 小时前
AIGC 应用工程师(3-5 年)面试题精讲:从基础到实战的系统备战清单
面试·大模型·aigc·agent·rag
boooooooom17 小时前
Pinia必学4大核心API:$patch/$reset/$subscribe/$onAction,用法封神!
javascript·vue.js·面试
试着17 小时前
【huawei】机考整理
学习·华为·面试·机试
石去皿18 小时前
【嵌入式就业6】计算机组成原理与操作系统核心机制:夯实底层基础
c++·面试·嵌入式