diff options
| author | Alan Viverette <alanv@google.com> | 2014-02-18 17:05:13 -0800 |
|---|---|---|
| committer | Alan Viverette <alanv@google.com> | 2014-02-18 17:05:13 -0800 |
| commit | 3e14162fc655e7a0dae61318911f3e29c07d0bf0 (patch) | |
| tree | 2f87013a4e2eaef2b0bdcebaa3be981a69690881 /core/java/android/widget/GridView.java | |
| parent | 22c5abff5fad7c70ab1751d56e030fc6e15a59f8 (diff) | |
Fix transient state, accessibility focus in ListView, GridView
Reverts portions of "Use transient state to preserve accessibility focus
in ListView," "Set transient state for focus container in ListView," and
"Restore A11y and keyboard focus positions after GridView layout."
Basically, using transient state here was bad and I should feel bad.
Replaces reverted code with better handling of accessibility properties
for scrapped views that are reused for the same stable ID.
BUG: 12701797
Change-Id: I7afcb2fe14413828435d1476b4f0f40108edd2dd
Diffstat (limited to 'core/java/android/widget/GridView.java')
| -rw-r--r-- | core/java/android/widget/GridView.java | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index 67430028cbbb..4ed48ff08f90 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -30,13 +30,13 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo; import android.view.animation.GridLayoutAnimationController; -import android.widget.AbsListView.AbsPositionScroller; -import android.widget.ListView.ListViewPositionScroller; import android.widget.RemoteViews.RemoteView; import java.lang.annotation.Retention; @@ -1222,22 +1222,32 @@ public class GridView extends AbsListView { setSelectedPositionInt(mNextSelectedPosition); - // Remember which child, if any, had accessibility focus. - final int accessibilityFocusPosition; - final View accessFocusedChild = getAccessibilityFocusedChild(); - if (accessFocusedChild != null) { - accessibilityFocusPosition = getPositionForView(accessFocusedChild); - accessFocusedChild.setHasTransientState(true); - } else { - accessibilityFocusPosition = INVALID_POSITION; - } + AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null; + View accessibilityFocusLayoutRestoreView = null; + int accessibilityFocusPosition = INVALID_POSITION; + + // Remember which child, if any, had accessibility focus. This must + // occur before recycling any views, since that will clear + // accessibility focus. + final ViewRootImpl viewRootImpl = getViewRootImpl(); + if (viewRootImpl != null) { + final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); + if (focusHost != null) { + final View focusChild = getAccessibilityFocusedChild(focusHost); + if (focusChild != null) { + if (!dataChanged || focusChild.hasTransientState() + || mAdapterHasStableIds) { + // The views won't be changing, so try to maintain + // focus on the current host and virtual view. + accessibilityFocusLayoutRestoreView = focusHost; + accessibilityFocusLayoutRestoreNode = viewRootImpl + .getAccessibilityFocusedVirtualView(); + } - // Ensure the child containing focus, if any, has transient state. - // If the list data hasn't changed, or if the adapter has stable - // IDs, this will maintain focus. - final View focusedChild = getFocusedChild(); - if (focusedChild != null) { - focusedChild.setHasTransientState(true); + // Try to maintain focus at the same position. + accessibilityFocusPosition = getPositionForView(focusChild); + } + } } // Pull all children into the RecycleBin. @@ -1324,13 +1334,22 @@ public class GridView extends AbsListView { mSelectorRect.setEmpty(); } - if (accessFocusedChild != null) { - accessFocusedChild.setHasTransientState(false); - - // If we failed to maintain accessibility focus on the previous - // view, attempt to restore it to the previous position. - if (!accessFocusedChild.isAccessibilityFocused() - && accessibilityFocusPosition != INVALID_POSITION) { + // Attempt to restore accessibility focus, if necessary. + final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost(); + if (newAccessibilityFocusedView == null) { + if (accessibilityFocusLayoutRestoreView != null + && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) { + final AccessibilityNodeProvider provider = + accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider(); + if (accessibilityFocusLayoutRestoreNode != null && provider != null) { + final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId( + accessibilityFocusLayoutRestoreNode.getSourceNodeId()); + provider.performAction(virtualViewId, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + } else { + accessibilityFocusLayoutRestoreView.requestAccessibilityFocus(); + } + } else if (accessibilityFocusPosition != INVALID_POSITION) { // Bound the position within the visible children. final int position = MathUtils.constrain( accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1); @@ -1341,10 +1360,6 @@ public class GridView extends AbsListView { } } - if (focusedChild != null) { - focusedChild.setHasTransientState(false); - } - mLayoutMode = LAYOUT_NORMAL; mDataChanged = false; if (mPositionScrollAfterLayout != null) { |
