Skip to content

Commit

Permalink
One of the child has accessibilityState (hasStateDescription triggers…
Browse files Browse the repository at this point in the history
… the announcement)

from facebook#33690 (comment)

I noticed that getStateDescription returns null even when adding accessibilityState. Calling setStateDescription will update the state description, which is not set via the react accessibilityState or other props.

Seems that the method [setViewState](https://github.com/fabriziobertoglio1987/react-native/blob/ad6732aa3576786d37478a729b112031dd94b682/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java#L254) does not call setStateDescription.

I will further investigate tomorrow.

<details><summary>View#setStateDescription</summary>
<p>

```java
    /**
     * Sets the {@link View}'s state description.
     * <p>
     * A state description briefly describes the states of the view and is primarily used
     * for accessibility support to determine how the states of a view should be presented to
     * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
     * it is used for customized state description (for example, "wifi, connected, three bars").
     * State description changes frequently while content description should change less often.
     * State description should be localized. For android widgets which have default state
     * descriptions, app developers can call this method to override the state descriptions.
     * Setting state description to null restores the default behavior.
     *
     * @param stateDescription The state description.
     * @see #getStateDescription()
     */
    @RemotableViewMethod
    public void setStateDescription(@nullable CharSequence stateDescription) {
        if (mStateDescription == null) {
            if (stateDescription == null) {
                return;
            }
        } else if (mStateDescription.equals(stateDescription)) {
            return;
        }
        mStateDescription = stateDescription;
        if (!TextUtils.isEmpty(stateDescription)
                && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
        }
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
            sendAccessibilityEventUnchecked(event);
        }
    }
```

</p>
</details>

This is the implementation of TalkBack [hasStateDescription](https://github.com/google/talkback/blob/6c0b475b7f52469e309e51bfcc13de58f18176ff/utils/src/main/java/com/google/android/accessibility/utils/AccessibilityNodeInfoUtils.java#L1672-L1677).

The following fields of the view are set with the accessibilityState:

- [checkable](https://github.com/fabriziobertoglio1987/react-native/blob/ad6732aa3576786d37478a729b112031dd94b682/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java#L411) => BOOLEAN_PROPERTY_CHECKABLE
- [enabled](https://github.com/fabriziobertoglio1987/react-native/blob/ad6732aa3576786d37478a729b112031dd94b682/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java#L408) => BOOLEAN_PROPERTY_ENABLED

<details><summary>setCheckable</summary>
<p>

https://github.com/aosp-mirror/platform_frameworks_base/blob/19e53cfdc8a5c6ef45c0adf2dd239576ddce5822/core/java/android/view/accessibility/AccessibilityNodeInfo.java#L2008

```java
  /**
   * Sets whether this node is checkable.
   * <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 checkable True if the node is checkable.
   *
   * @throws IllegalStateException If called from an AccessibilityService.
   */
  public void setCheckable(boolean checkable) {
      setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
  }
```

</p>
</details>

<details><summary>setEnabled</summary>
<p>

https://github.com/aosp-mirror/platform_frameworks_base/blob/19e53cfdc8a5c6ef45c0adf2dd239576ddce5822/core/java/android/view/accessibility/AccessibilityNodeInfo.java#L2227

```java
    /**
     * Sets whether this node is enabled.
     * <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 enabled True if the node is enabled.
     *
     * @throws IllegalStateException If called from an AccessibilityService.
     */
    public void setEnabled(boolean enabled) {
        setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
    }
```

</p>
</details>

The implementation of `hasStateDescription` is still valid
  • Loading branch information
fabOnReact committed Jun 8, 2022
1 parent d5f4c9c commit c17f00e
Showing 1 changed file with 12 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -341,50 +341,18 @@ class AutomaticContentGrouping extends React.Component<{}> {

<RNTesterBlock title="One of the child has accessibilityState (hasStateDescription triggers the announcement)">
<View accessible={true} accessibilityRole="button">
<View>
<Text accessible={false}>Text number 1</Text>
<Image
source={{
uri: 'https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png',
}}
style={{height: 50, width: 50}}
/>
</View>
</View>
</RNTesterBlock>

<RNTesterBlock title="One of the child has accessibilityState (hasStateDescription triggers the announcement)">
<View
accessible={true}
accessibilityHint="this is parent hint"
accessibilityState={{
checked: true,
selected: true,
disabled: true,
busy: true,
expanded: true,
}}>
<View
accessibilityState={{
checked: true,
selected: true,
disabled: true,
busy: true,
expanded: true,
}}>
<Text
accessibilityState={{
checked: true,
selected: true,
disabled: true,
busy: true,
expanded: true,
}}
accessibilityState={{checked: true}}
accessible={false}>
Text number 1
</Text>
</View>
<Text
accessible={false}
accessibilityLabel="label for text number 1">
Text number 1
</Text>
<Text
style={{backgroundColor: 'red', height: 40, width: 40}}
accessible={false}
accessibilityState={{checked: true}}
accessibilityLabel="label for last child"
accessibilityRole="image"
/>
</View>
</RNTesterBlock>
</View>
Expand Down

0 comments on commit c17f00e

Please sign in to comment.