diff options
| -rw-r--r-- | core/java/android/view/View.java | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index eb591c1bfa86..0fa3ddc1a4f0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8408,11 +8408,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public void clearAccessibilityFocus() { clearAccessibilityFocusNoCallbacks(); - // Clear the global reference of accessibility focus if this - // view or any of its descendants had accessibility focus. - ViewRootImpl viewRootImpl = getViewRootImpl(); + + // Clear the global reference of accessibility focus if this view or + // any of its descendants had accessibility focus. This will NOT send + // an event or update internal state if focus is cleared from a + // descendant view, which may leave views in inconsistent states. + final ViewRootImpl viewRootImpl = getViewRootImpl(); if (viewRootImpl != null) { - View focusHost = viewRootImpl.getAccessibilityFocusedHost(); + final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { viewRootImpl.setAccessibilityFocus(null, null); } @@ -8688,6 +8691,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void setImportantForAccessibility(int mode) { final int oldMode = getImportantForAccessibility(); if (mode != oldMode) { + final boolean hideDescendants = + mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; + + // If this node or its descendants are no longer important, try to + // clear accessibility focus. + if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) { + final View focusHost = findAccessibilityFocusHost(hideDescendants); + if (focusHost != null) { + focusHost.clearAccessibilityFocus(); + } + } + // If we're moving between AUTO and another state, we might not need // to send a subtree changed notification. We'll store the computed // importance, since we'll need to check it later to make sure. @@ -8707,6 +8722,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the view within this view's hierarchy that is hosting + * accessibility focus. + * + * @param searchDescendants whether to search for focus in descendant views + * @return the view hosting accessibility focus, or {@code null} + */ + private View findAccessibilityFocusHost(boolean searchDescendants) { + if (isAccessibilityFocusedViewOrHost()) { + return this; + } + + if (searchDescendants) { + final ViewRootImpl viewRoot = getViewRootImpl(); + if (viewRoot != null) { + final View focusHost = viewRoot.getAccessibilityFocusedHost(); + if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { + return focusHost; + } + } + } + + return null; + } + + /** * Computes whether this view should be exposed for accessibility. In * general, views that are interactive or provide information are exposed * while views that serve only as containers are hidden. |