diff options
| author | 2017-11-07 15:28:21 -0800 | |
|---|---|---|
| committer | 2017-11-27 17:03:27 -0800 | |
| commit | 1e6ecc69b71c4c8acd792461a050ae0f79a87bd9 (patch) | |
| tree | 75d0229e9a0f992b28056034e287c99cf66e838d | |
| parent | d12e276f6ae35a1e889c6d4de97688903c49001b (diff) | |
New API to specify accessibility focus grouping
We've been telling developers to use the focusable
attribute to control grouping for accessibility focus. This
new API can be used in place of the focusable attribute.
Bug: 63889180
Test: Adding new CTS tests for new api.
Change-Id: I5cbeb736a3b206f87aa3d921a39c43861c7ff082
| -rw-r--r-- | api/current.txt | 5 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 52 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityNodeInfo.java | 33 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 6 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 |
6 files changed, 98 insertions, 1 deletions
diff --git a/api/current.txt b/api/current.txt index 93b6b424458f..deb9fe890806 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1119,6 +1119,7 @@ package android { field public static final int scheme = 16842791; // 0x1010027 field public static final int screenDensity = 16843467; // 0x10102cb field public static final int screenOrientation = 16842782; // 0x101001e + field public static final int screenReaderFocusable = 16844148; // 0x1010574 field public static final int screenSize = 16843466; // 0x10102ca field public static final int scrollHorizontally = 16843099; // 0x101015b field public static final int scrollIndicators = 16844006; // 0x10104e6 @@ -46331,6 +46332,7 @@ package android.view { method public boolean isPressed(); method public boolean isSaveEnabled(); method public boolean isSaveFromParentEnabled(); + method public boolean isScreenReaderFocusable(); method public boolean isScrollContainer(); method public boolean isScrollbarFadingEnabled(); method public boolean isSelected(); @@ -46550,6 +46552,7 @@ package android.view { method public void setSaveFromParentEnabled(boolean); method public void setScaleX(float); method public void setScaleY(float); + method public void setScreenReaderFocusable(boolean); method public void setScrollBarDefaultDelayBeforeFade(int); method public void setScrollBarFadeDuration(int); method public void setScrollBarSize(int); @@ -47968,6 +47971,7 @@ package android.view.accessibility { method public boolean isLongClickable(); method public boolean isMultiLine(); method public boolean isPassword(); + method public boolean isScreenReaderFocusable(); method public boolean isScrollable(); method public boolean isSelected(); method public boolean isShowingHintText(); @@ -48023,6 +48027,7 @@ package android.view.accessibility { method public void setParent(android.view.View, int); method public void setPassword(boolean); method public void setRangeInfo(android.view.accessibility.AccessibilityNodeInfo.RangeInfo); + method public void setScreenReaderFocusable(boolean); method public void setScrollable(boolean); method public void setSelected(boolean); method public void setShowingHintText(boolean); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e36a2989afbc..345e30030534 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2929,6 +2929,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_TEMPORARY_DETACH * 1 PFLAG3_NO_REVEAL_ON_FOCUS * 1 PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT + * 1 PFLAG3_SCREEN_READER_FOCUSABLE * |-------|-------|-------|-------| */ @@ -3209,6 +3210,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000; + /** + * Works like focusable for screen readers, but without the side effects on input focus. + * @see #setScreenReaderFocusable(boolean) + */ + private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000; + /* End of masks for mPrivateFlags3 */ /** @@ -5344,6 +5351,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setDefaultFocusHighlightEnabled(a.getBoolean(attr, true)); } break; + case R.styleable.View_screenReaderFocusable: + if (a.peekValue(attr) != null) { + setScreenReaderFocusable(a.getBoolean(attr, false)); + } + break; } } @@ -8394,6 +8406,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, info.setEnabled(isEnabled()); info.setClickable(isClickable()); info.setFocusable(isFocusable()); + info.setScreenReaderFocusable(isScreenReaderFocusable()); info.setFocused(isFocused()); info.setAccessibilityFocused(isAccessibilityFocused()); info.setSelected(isSelected()); @@ -10350,6 +10363,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns whether the view should be treated as a focusable unit by screen reader + * accessibility tools. + * @see #setScreenReaderFocusable(boolean) + * + * @return Whether the view should be treated as a focusable unit by screen reader. + */ + public boolean isScreenReaderFocusable() { + return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0; + } + + /** + * When screen readers (one type of accessibility tool) decide what should be read to the + * user, they typically look for input focusable ({@link #isFocusable()}) parents of + * non-focusable text items, and read those focusable parents and their non-focusable children + * as a unit. In some situations, this behavior is desirable for views that should not take + * input focus. Setting an item to be screen reader focusable requests that the view be + * treated as a unit by screen readers without any effect on input focusability. The default + * value of {@code false} lets screen readers use other signals, like focusable, to determine + * how to group items. + * + * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader + * accessibility tools. + */ + public void setScreenReaderFocusable(boolean screenReaderFocusable) { + int pflags3 = mPrivateFlags3; + if (screenReaderFocusable) { + pflags3 |= PFLAG3_SCREEN_READER_FOCUSABLE; + } else { + pflags3 &= ~PFLAG3_SCREEN_READER_FOCUSABLE; + } + + if (pflags3 != mPrivateFlags3) { + mPrivateFlags3 = pflags3; + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } + } + + /** * Find the nearest view in the specified direction that can take focus. * This does not actually give focus to that view. * diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 929beaea42b8..122df934111d 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2591,7 +2591,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean alreadyDispatchedToNewTouchTarget = false; if (!canceled && !intercepted) { - // If the event is targeting accessiiblity focus we give it to the + // If the event is targeting accessibility focus we give it to the // view that has accessibility focus and if it does not handle it // we clear the flag and dispatch the event to all children as usual. // We are looking up the accessibility focused host to avoid keeping diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 9bdd3ffc9fb2..faea9200c522 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -635,6 +635,8 @@ public class AccessibilityNodeInfo implements Parcelable { private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000; + private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000; + private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000; /** @@ -2321,6 +2323,37 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Returns whether the node is explicitly marked as a focusable unit by a screen reader. Note + * that {@code false} indicates that it is not explicitly marked, not that the node is not + * a focusable unit. Screen readers should generally used other signals, such as + * {@link #isFocusable()}, or the presence of text in a node, to determine what should receive + * focus. + * + * @return {@code true} if the node is specifically marked as a focusable unit for screen + * readers, {@code false} otherwise. + * + * @see View#isScreenReaderFocusable() + */ + public boolean isScreenReaderFocusable() { + return getBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE); + } + + /** + * Sets whether the node should be considered a focusable unit by a screen reader. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param screenReaderFocusable {@code true} if the node is a focusable unit for screen readers, + * {@code false} otherwise. + */ + public void setScreenReaderFocusable(boolean screenReaderFocusable) { + setBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE, screenReaderFocusable); + } + + /** * Returns whether the node's text represents a hint for the user to enter text. It should only * be {@code true} if the node has editable text. * diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 0eefec91e390..9a0eafdb7c77 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3021,6 +3021,12 @@ <!-- Whether this View should use a default focus highlight when it gets focused but doesn't have {@link android.R.attr#state_focused} defined in its background. --> <attr name="defaultFocusHighlightEnabled" format="boolean" /> + + <!-- Whether this view should be treated as a focusable unit by screen reader accessibility + tools. See {@link android.view.View#setScreenReaderFocusable(boolean)}. The default + value, {@code false}, leaves the screen reader to consider other signals, such as + focusability or the presence of text, to decide what it focus.--> + <attr name="screenReaderFocusable" format="boolean" /> </declare-styleable> <!-- Attributes that can be assigned to a tag for a particular View. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index d3533fe6e79f..812595d10d0b 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2852,6 +2852,7 @@ <public name="compileSdkVersion" /> <!-- @hide For use by platform and tools only. Developers should not specify this value. --> <public name="compileSdkVersionCodename" /> + <public name="screenReaderFocusable" /> </public-group> <public-group type="style" first-id="0x010302e0"> |