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

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

带注释的代码如下: 由于事件分发这一块分支条件太多,所以必须结合情景来分析: 前提:父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,导致后续所有的事件都会被拦截。

相关推荐
li星野2 小时前
RAG优化系列:切块策略深度解析——固定长度 vs 自适应标题(含AI评估与面试指南)
人工智能·面试·职场和发展
devilnumber3 小时前
HAProxy 重点精讲 + 背诵记忆点(面试速记版)
面试·职场和发展
kisshyshy3 小时前
# 🔥 数组去重:从双重循环到 Set,面试官想听什么?
javascript·面试
Byron__4 小时前
Spring核心面试知识点(IoC/Bean生命周期/AOP/事务)
java·spring·面试
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题 第78题】【Mysql篇】第8题:解释下最左前缀原则?
java·开发语言·数据库·mysql·面试
小江的记录本5 小时前
【JVM虚拟机】垃圾回收GC:垃圾判定算法:引用计数法、可达性分析算法(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·spring·面试
jiayong235 小时前
智能体常见面试问题及详细解答
ai·面试·职场和发展·智能体·vibe coding
Byron__5 小时前
JVM垃圾回收与调优核心面试笔记(引用计数/GC算法/CMS/G1/参数调优)
java·jvm·笔记·面试
罗超驿6 小时前
6.Java多线程详解:Thread类、线程属性与start()方法深度解析
java·开发语言·面试·java-ee
英俊潇洒美少年7 小时前
前端主流状态管理全家桶:Vuex/Pinia/Redux/Zustand/MobX 从入门到原理、实战、面试全解
前端·面试·职场和发展