Fix problem with ListView accessibility focus
A scrap view was retaining accessibility focus, leading to
a confusing experience for screen reader users.
Part of the problem is that views can change even when the
adapter has stable ids. This change tightens the condition
for restoring a11y focus to the same view.
AbsListView also allowed scrap views to maintain a11y focus.
While this may make sense if the views will be reused, it is
wrong if the views are not reused.
Bug: 29403113
Test: Verified that a11y focus stays put when toggling the
preference: Settings -> System -> Language & input ->
Virtual keyboards -> Advanced -> Symbol for physical keyboard
Change-Id: Ie4a15027088f158d9ed4bb3f3eeff5a288c25832
(cherry picked from commit ab4717aa2a7d0e19f4b08b2c851a541f9b0c9c6b)
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1937187..99b91bd 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6873,9 +6873,11 @@
mTransientStateViews.put(position, scrap);
} else {
// Otherwise, we'll have to remove the view and start over.
+ clearScrapForRebind(scrap);
getSkippedScrap().add(scrap);
}
} else {
+ clearScrapForRebind(scrap);
if (mViewTypeCount == 1) {
mCurrentScrap.add(scrap);
} else {
@@ -7098,12 +7100,12 @@
}
} else if (params.scrappedFromPosition == position) {
final View scrap = scrapViews.remove(i);
- clearAccessibilityFromScrap(scrap);
+ clearScrapForRebind(scrap);
return scrap;
}
}
final View scrap = scrapViews.remove(size - 1);
- clearAccessibilityFromScrap(scrap);
+ clearScrapForRebind(scrap);
return scrap;
} else {
return null;
@@ -7117,7 +7119,7 @@
}
}
- private void clearAccessibilityFromScrap(View view) {
+ private void clearScrapForRebind(View view) {
view.clearAccessibilityFocus();
view.setAccessibilityDelegate(null);
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1c0c4ef..12e35a1 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1639,7 +1639,7 @@
final View focusChild = getAccessibilityFocusedChild(focusHost);
if (focusChild != null) {
if (!dataChanged || isDirectChildHeaderOrFooter(focusChild)
- || focusChild.hasTransientState() || mAdapterHasStableIds) {
+ || (focusChild.hasTransientState() && mAdapterHasStableIds)) {
// The views won't be changing, so try to maintain
// focus on the current host and virtual view.
accessibilityFocusLayoutRestoreView = focusHost;