-
Notifications
You must be signed in to change notification settings - Fork 24.7k
[Android] Selected State does not annonce when TextInput Component selected #31144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Android] Selected State does not annonce when TextInput Component selected #31144
Conversation
This comment has been minimized.
This comment has been minimized.
Base commit: ac7ba3e |
Base commit: ac7ba3e |
packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js
Outdated
Show resolved
Hide resolved
@@ -166,8 +166,12 @@ public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilitySta | |||
if (accessibilityState == null) { | |||
return; | |||
} | |||
if (accessibilityState.hasKey("selected")) { | |||
view.setSelected(accessibilityState.getBoolean("selected")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the java test case does not verify that view.setSelected(true)
is invoked, but just verifies view.setTag(R.id.accessibility_state, accessibilityState)
, I will update the test to verify those scenarios.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved with commit 79486b5 more info at #31144 (comment) 🙏 ☮️
packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js
Outdated
Show resolved
Hide resolved
<View> | ||
<TextInput | ||
accessible={true} | ||
accessibilityState={{selected: this.state.focused}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @blavalla - Should the TextInput component always announce "selected" if it's focused and always announce "not selected" if it's blurred? Should this behavior be built into the component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is some confusion here as to the usage of the "selected" property, which is not surprising given its vague name, and how other things (like text within the input for example) can also be "selected"!
This property is meant to represent an element that is highlighted visually for some reason. Maybe there's a list of text inputs, and only one of them is active at a time for some reason, and is highlighted in yellow to show this visually. This item would be "selected", while the others would be "not selected".
It doesn't really pertain to focus being within the input itself, or whether that input is currently being edited, or anything like that.
This same selected property can be applied to any type of view, and the issue here is simply that it doesn't work for <TextInput>
like it does for <View>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, thank you for the explanation! So the goal of the issue is just to allow the selected state to be set at the user's discretion, and not to always set it at any one time.
@@ -716,10 +725,8 @@ class SetAccessibilityFocusExample extends React.Component<{}> { | |||
|
|||
const onClose = () => { | |||
if (myRef && myRef.current) { | |||
AccessibilityInfo.sendAccessiblityEvent_unstable( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new method does the same thing as setAccessibilityFocus does, with the exception that this unstable method is fabric-friendly! Did this method not work for you? We don't want to change it back if we can avoid it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kacieb Yes, I experienced this issue with the current master branch
Do you want me to keep this change, reverse it or to investigate and fix the method?
I can not find sendAccessiblityEvent_unstable
in our codebase. Thanks a lot 🙏 ☮️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah got it, maybe this only works internally currently. Since this is an RNTester example, it should be ok to keep this change for now, and we can resolve it internally later.
cc @JoshuaGross and @mdvacca for awareness!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a missing "i", it should be : "sendAccessibilityEvent_unstable" instead of "sendAccessiblityEvent_unstable"
Hey! Thanks so much for working on this! I'm excited for this fix. I'm adding in @blavalla as a reviewer to help on the Android side! |
Just to add further clarification here, when referring to "focus" in the original issue, it is meant to mean screenreader focus, not keyboard focus. Android unfortunately uses the same term for both of these concepts, so discussing them can get confusing! Keyboard-focus behavior is currently working as expected on TextInput, so doesn't need to be changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code analysis results:
eslint
found some issues. Runyarn lint --fix
to automatically fix problems.
packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Android code in BaseViewManager.java looks good to me.
I am not really familiar with how the testing system works here, and why it's not able to mock out the view though. @kacieb, is there anyone on the React Core team who knows this system and could take a look?
Sorry, I think I'm not understanding what you mean by this? Is the test not working as expected? |
Sorry, I may have been looking at something thats not an issue anymore. There was a few comments about the tests not working here: @fabriziobertoglio1987, just to confirm, did you get the tests working correctly? |
The test below does not fail in the master branch as it does not verify the new behaviour added with pr facebook#31144 The test previously would just verify that the `mView` had a tag `R.id.accessibility_state` with value equal to variable `accessibilityState` ```java assertThat(mView.getTag(R.id.accessibility_state)).isEqualTo(accessibilityState) ```` https://github.com/facebook/react-native/blob/a6cc5871e68b63e2f29bcb3610968dd33b926694/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java#L72-L77 Now the test verifies that `mView.isSelected()` is true after passing `accessibilityState.selected` true. I previously tried to run this verification by mocking `mView` instance, but it is not possible and I later found the public method in the Android sourcecode. https://developer.android.com/reference/android/view/View#isSelected() ```java /** * Indicates the selection state of this view. * * @return true if the view is selected, false otherwise */ @ViewDebug.ExportedProperty @InspectableProperty(hasAttributeId = false) public boolean isSelected() { return (mPrivateFlags & PFLAG_SELECTED) != 0; } ``` Related to https://github.com/facebook/react-native/pull/31144/files#r595064322
Thanks a lot @blavalla @kacieb for your Feedback! The comment https://github.com/facebook/react-native/pull/31144/files#r595007827 is now solved with commit 79486b5 The test discussed would not fail in the master branch as it does not verify the new behaviour added with pr #31144 in java. assertThat(mView.getTag(R.id.accessibility_state)).isEqualTo(accessibilityState) react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java Lines 72 to 77 in a6cc587
Now the test verifies that https://developer.android.com/reference/android/view/View#isSelected() /**
* Indicates the selection state of this view.
*
* @return true if the view is selected, false otherwise
*/
@ViewDebug.ExportedProperty
@InspectableProperty(hasAttributeId = false)
public boolean isSelected() {
return (mPrivateFlags & PFLAG_SELECTED) != 0;
} Thanks a lot to Blavalla and Kacie Bawiec. |
is a useful reminder in the future to fix fabric method sendAccessiblityEvent_unstable in the future https://github.com/facebook/react-native/pull/31144/files#r596273281
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code analysis results:
eslint
found some issues. Runyarn lint --fix
to automatically fix problems.
packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js
Outdated
Show resolved
Hide resolved
I have been working for a while with typescript and forgot to update my vim setup :-)
I removed the prop react-native/Libraries/Components/TextInput/TextInput.js Lines 414 to 415 in 6012e98
react-native/Libraries/Components/View/ViewPropTypes.js Lines 423 to 426 in 6012e98
|
@kacieb has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Thank you @fabriziobertoglio1987 for this contribution! I would like to give you a shout-out on Twitter and include you in our end-of-month issues update for your contribution. Do you have a Twitter we can tag? |
Thanks a lot @amarlette I don't use often twitter and I would prefer that you use my github account https://github.com/fabriziobertoglio1987. I have an old twitter account https://twitter.com/fabri_on_rails. Feel free to use any of those account (twitter and/or github). I wish you a good day ☮️ 🙏 😃 |
Summary
This issue fixes #30955 and is a follow up to pr #24608 which added the basic Accessibility functionalities to React Native.
TextInput should announce "selected" to the user when screenreader focused.
The focus is moved to the TextInput by navigating with the screenreader to the TextInput.
This PR adds call to View#setSelected in BaseViewManager https://developer.android.com/reference/android/view/View#setSelected(boolean)
The View#setSelected method definition https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/view/View.java
VoiceOver and TalkBack was tested with video samples included below.
Changelog
[Android] [Fixed] - Fix Selected State does not announce when TextInput Component selected on Android
Test Plan
CLICK TO OPEN TESTS RESULTS
ENABLE THE AUDIO to hear the TalkBack announcing SELECTED when the user taps on the TextInput
2021-03-18.16-33-01.mp4
2021-03-18.16-32-39.mp4
The functionality does not present issues on iOS
RecordIt-1616079277.mp4