桌面列表小部件不能点击的问题分析
问题复现
拖动谷歌浏览器的小部件到桌面,"打开新的标签页"不能点击,没有按压效果
小部件布局
正常情况点击事件传递
不能点击的情况
也会触发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();
+ }
}
}