桌面列表小部件不能点击的问题分析

桌面列表小部件不能点击的问题分析

问题复现

拖动谷歌浏览器的小部件到桌面,"打开新的标签页"不能点击,没有按压效果

小部件布局

正常情况点击事件传递

不能点击的情况

也会触发AbsListView.onTounchDown和AbsListView.onTouchUP,但没有按压效果和点击事件触发

分析:

拖动小部件放到桌面时会触发AbsListView的onAttachedToWindow,mDataChanged被赋值为true frameworks/base/core/java/android/widget/AbsListView.java

js 复制代码
    protected void onAttachedToWindow() {
        if (mAdapter != null && mDataSetObserver == null) {
...
            mDataChanged = true;
        }
    }

mDataChanged = true,列表的点击事件PerformClick.run无法处理 frameworks/base/core/java/android/widget/AbsListView.java

js 复制代码
    private void onTouchUp(MotionEvent ev) {
        switch (mTouchMode) {
            case TOUCH_MODE_DOWN:
            case TOUCH_MODE_TAP:
            case TOUCH_MODE_DONE_WAITING:
...
                        if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
...
                            if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
...
                                layoutChildren();
                                child.setPressed(true);
...
                                setPressed(true);
...
                                mTouchModeReset = new Runnable() {
                                    @Override
                                    public void run() {
                                        mTouchModeReset = null;
                                        mTouchMode = TOUCH_MODE_REST;
                                        child.setPressed(false);
                                        setPressed(false);
                                        if (!mDataChanged && !mIsDetaching
                                                && isAttachedToWindow()) {
                                            performClick.run();
                                        }
                                    }
                                };
                                postDelayed(mTouchModeReset,
                                        ViewConfiguration.getPressedStateDuration());
..
                    }
                }

安卓15无此问题:

触摸一下就会触发DOWN,MOVE,MOVE,UP 对比Android14机器

只触发DOWN,UP

因此Android 15会在点击时多处理move事件

move事件处理中mDataChanged为true时,会调用layoutChildren(),此函数中可以将mDataChanged重新置为false,onTouchUp就可以正常触发点击事件 frameworks/base/core/java/android/widget/AbsListView.java

js 复制代码
    private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
...
        if (mDataChanged) {
            layoutChildren();
        }

frameworks/base/core/java/android/widget/ListView.java

js 复制代码
    protected void layoutChildren() {
...
            mLayoutMode = LAYOUT_NORMAL;
            mDataChanged = false;
...
    }

解决

此问题为AOSP的原生bug,在onAttachedToWindow后重新请求布局更新 frameworks/base/core/java/android/widget/AbsListView.java

js 复制代码
    protected void onAttachedToWindow() {
....
        if (mAdapter != null && mDataSetObserver == null) {
.....
            mDataChanged = true;
...
+            if (mAdapter instanceof RemoteViewsAdapter) {
+                requestLayout();
+            }
        }
    }
相关推荐
devlei2 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
阿拉斯攀登5 小时前
从入门到实战:CMake 与 Android JNI/NDK 开发全解析
android·linux·c++·yolo·cmake
冬奇Lab5 小时前
相机录像流程:MediaRecorder与Camera2的协作之道
android·音视频开发·源码阅读
麦客奥德彪6 小时前
Jetpack Compose 常用开发总结
android
麦客奥德彪6 小时前
Jetpack Compose Modifier 完全指南
android
Mac的实验室8 小时前
(2026年最新)解决谷歌账号注册设备扫码短信发送失败无法验证难题(100%通过无需扫码验证)
android·google·程序员
半条咸鱼9 小时前
如何通过 ADB 连接安卓设备(USB + 无线 TCP/IP)
android
huwuhang10 小时前
斐讯盒子N1_YYFROM固件_webview119更新版附安卓专用遥控器刷机固工具USB_Burning_Tool
android
qq_3520186810 小时前
android 状态栏高度获取
android
AirDroid_cn10 小时前
安卓15平板分屏比例能到1:9吗?极限分屏设置教程
android·智能手机