summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget/ListView.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/widget/ListView.java')
-rw-r--r--core/java/android/widget/ListView.java62
1 files changed, 62 insertions, 0 deletions
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e011c13..03507b5 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -29,6 +29,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.MathUtils;
import android.util.SparseBooleanArray;
import android.view.FocusFinder;
import android.view.KeyEvent;
@@ -37,6 +38,7 @@ import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.RemoteViews.RemoteView;
@@ -1490,6 +1492,10 @@ public class ListView extends AbsListView {
View focusLayoutRestoreView = null;
+ AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
+ View accessibilityFocusLayoutRestoreView = null;
+ int accessibilityFocusPosition = INVALID_POSITION;
+
// Remember stuff we will need down below
switch (mLayoutMode) {
case LAYOUT_SET_SELECTION:
@@ -1584,6 +1590,30 @@ public class ListView extends AbsListView {
requestFocus();
}
+ // Remember which child, if any, had accessibility focus.
+ final ViewRootImpl viewRootImpl = getViewRootImpl();
+ if (viewRootImpl != null) {
+ final View accessFocusedView = viewRootImpl.getAccessibilityFocusedHost();
+ if (accessFocusedView != null) {
+ final View accessFocusedChild = findAccessibilityFocusedChild(
+ accessFocusedView);
+ if (accessFocusedChild != null) {
+ if (!dataChanged || isDirectChildHeaderOrFooter(accessFocusedChild)) {
+ // If the views won't be changing, try to maintain
+ // focus on the current view host and (if
+ // applicable) its virtual view.
+ accessibilityFocusLayoutRestoreView = accessFocusedView;
+ accessibilityFocusLayoutRestoreNode = viewRootImpl
+ .getAccessibilityFocusedVirtualView();
+ } else {
+ // Otherwise, try to maintain focus at the same
+ // position.
+ accessibilityFocusPosition = getPositionForView(accessFocusedChild);
+ }
+ }
+ }
+ }
+
// Clear out old views
detachAllViewsFromParent();
recycleBin.removeSkippedScrap();
@@ -1682,6 +1712,22 @@ public class ListView extends AbsListView {
}
}
+ // Attempt to restore accessibility focus.
+ if (accessibilityFocusLayoutRestoreNode != null) {
+ accessibilityFocusLayoutRestoreNode.performAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ } else if (accessibilityFocusLayoutRestoreView != null) {
+ accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
+ } else if (accessibilityFocusPosition != INVALID_POSITION) {
+ // Bound the position within the visible children.
+ final int position = MathUtils.constrain(
+ (accessibilityFocusPosition - mFirstPosition), 0, (getChildCount() - 1));
+ final View restoreView = getChildAt(position);
+ if (restoreView != null) {
+ restoreView.requestAccessibilityFocus();
+ }
+ }
+
// tell focus view we are done mucking with it, if it is still in
// our view hierarchy.
if (focusLayoutRestoreView != null
@@ -1713,6 +1759,22 @@ public class ListView extends AbsListView {
}
/**
+ * @param focusedView the view that has accessibility focus.
+ * @return the direct child that contains accessibility focus.
+ */
+ private View findAccessibilityFocusedChild(View focusedView) {
+ ViewParent viewParent = focusedView.getParent();
+ while ((viewParent instanceof View) && (viewParent != this)) {
+ focusedView = (View) viewParent;
+ viewParent = viewParent.getParent();
+ }
+ if (!(viewParent instanceof View)) {
+ return null;
+ }
+ return focusedView;
+ }
+
+ /**
* @param child a direct child of this list.
* @return Whether child is a header or footer view.
*/