概述
在 Android 应用程序中,ListView 是一种常用的控件,用于显示可滚动列表数据。然而,当在鼠标操作模式下使用 ListView 时,可能会遇到一个问题:点击列表项时,列表会回滚到指定位置,这可能会导致用户体验不佳。
分析
通过测试发现, 回滚的位置与列表的选中项位置有关系.
在启动activity后, 不执行其他操作时, 通过滚轮直接滚动到列表最下方, 再点击按键, 调用了adapter.notifyDataSetChanged
列表回滚;
dumpsys
dumpsys activity com.android.tester/.cases.ListViewBackground
出现回滚时
View Hierarchy:
DecorView@4ef06ab[ListViewBackground]
com.android.internal.widget.ActionBarOverlayLayout{1102108 V.E...... ........ 0,0-1920,1080 #1020230 android:id/decor_content_parent}
android.widget.FrameLayout{21eb0a1 V.E...... ........ 0,96-1920,1080 #1020002 android:id/content}
android.widget.LinearLayout{e6872c6 V.E...... ........ 0,0-1920,984}
android.widget.ListView{956287 VFED.VC.. .F...... 0,0-1920,984 #7f030002 app:id/lvRight}
android.widget.LinearLayout{f0a45b4 V.E...... ..S..... 0,0-1920,173}
android.widget.TextView{5d4b5dd V.ED..... ..S..... 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{e8f552 VFED..C.. ..S..... 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{37d149e V.E...... ........ 0,175-1920,348}
android.widget.TextView{8be1b7f V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{88c974c VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{d5ba023 V.E...... ........ 0,350-1920,523}
android.widget.TextView{8e00920 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{8ebd2d9 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{abdc395 V.E...... ........ 0,525-1920,698}
android.widget.TextView{ea1dcaa V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{1a2f09b VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{a91dc38 V.E...... ........ 0,700-1920,873}
android.widget.TextView{c840411 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{3991976 VFED..C.. ....H... 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{535fb77 V.E...... ........ 0,875-1920,1048}
android.widget.TextView{fa483e4 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{f93d04d VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
com.android.internal.widget.ActionBarContainer{3f55702 V.ED..... ........ 0,0-1920,96 #102018e android:id/action_bar_container}
android.widget.Toolbar{d84d813 V.E...... ........ 0,0-1920,96 #102018d android:id/action_bar}
android.widget.TextView{d17fa50 V.ED..... ........ 36,27-122,68}
com.android.internal.widget.ActionBarContextView{b5a2449 G.E...... ......I. 0,0-0,0 #1020192 android:id/action_context_bar}
在启动activity后, 点击列表项(不是BTN所在区域), 通过滚轮直接滚动到列表最下方, 再点击按键, 调用了adapter.notifyDataSetChanged
列表不回滚;
不会滚
View Hierarchy:
DecorView@4ef06ab[ListViewBackground]
com.android.internal.widget.ActionBarOverlayLayout{1102108 V.E...... ........ 0,0-1920,1080 #1020230 android:id/decor_content_parent}
android.widget.FrameLayout{21eb0a1 V.E...... ........ 0,96-1920,1080 #1020002 android:id/content}
android.widget.LinearLayout{e6872c6 V.E...... ........ 0,0-1920,984}
android.widget.ListView{956287 VFED.VC.. .F..H... 0,0-1920,984 #7f030002 app:id/lvRight}
android.widget.LinearLayout{f0a45b4 V.E...... ........ 0,0-1920,173}
android.widget.TextView{5d4b5dd V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{e8f552 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{d5ba023 V.E...... ........ 0,175-1920,348}
android.widget.TextView{8e00920 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{8ebd2d9 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{37d149e V.E...... ........ 0,350-1920,523}
android.widget.TextView{8be1b7f V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{88c974c VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{abdc395 V.E...... ........ 0,525-1920,698}
android.widget.TextView{ea1dcaa V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{1a2f09b VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{a91dc38 V.E...... ........ 0,700-1920,873}
android.widget.TextView{c840411 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{3991976 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
android.widget.LinearLayout{535fb77 V.E...... ........ 0,875-1920,1048}
android.widget.TextView{fa483e4 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
android.widget.Button{f93d04d VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
com.android.internal.widget.ActionBarContainer{3f55702 V.ED..... ........ 0,0-1920,96 #102018e android:id/action_bar_container}
android.widget.Toolbar{d84d813 V.E...... ........ 0,0-1920,96 #102018d android:id/action_bar}
android.widget.TextView{d17fa50 V.ED..... ........ 36,27-122,68}
com.android.internal.widget.ActionBarContextView{b5a2449 G.E...... ......I. 0,0-0,0 #1020192 android:id/action_context_bar}
View状态输出的源码:
frameworks/base/core/java/android/view/View.java
public String toString() {
StringBuilder out = new StringBuilder(128);
out.append(getClass().getName());
out.append('{');
out.append(Integer.toHexString(System.identityHashCode(this)));
out.append(' ');
switch (mViewFlags&VISIBILITY_MASK) {
case VISIBLE: out.append('V'); break;
case INVISIBLE: out.append('I'); break;
case GONE: out.append('G'); break;
default: out.append('.'); break;
}
out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
out.append(' ');
out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
out.append('p');
} else {