OSDN Git Service

Fix problem with ListView accessibility focus
authorPhil Weaver <pweaver@google.com>
Thu, 23 Mar 2017 19:21:53 +0000 (12:21 -0700)
committerPhil Weaver <pweaver@google.com>
Wed, 29 Mar 2017 15:34:30 +0000 (15:34 +0000)
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)

core/java/android/widget/AbsListView.java
core/java/android/widget/ListView.java

index 1937187..99b91bd 100644 (file)
@@ -6873,9 +6873,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                     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 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                         }
                     } 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 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
             }
         }
 
-        private void clearAccessibilityFromScrap(View view) {
+        private void clearScrapForRebind(View view) {
             view.clearAccessibilityFocus();
             view.setAccessibilityDelegate(null);
         }
index 1c0c4ef..12e35a1 100644 (file)
@@ -1639,7 +1639,7 @@ public class ListView extends AbsListView {
                     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;