Skip to content

Commit f0e80ae

Browse files
Emily Janzerfacebook-github-bot
Emily Janzer
authored andcommitted
Set selection to end of text input on accessibility click
Summary: When we render a text input that already has a text value (<TextInput value="123" />), its selection (cursor) is automatically set to the end of the text. However, when you swipe to focus the text input with TalkBack, Android decides it needs to clear the selection, which moves the cursor back to the beginning of the text input. This is probably not what you want if you're editing some text that's already there. Ideally we would just keep the selection at the end, but I don't know how to prevent this from happening - it seems to be part of how TextView handles the accessibility focus event? So instead I'm just explicitly setting the selection to the end of the text in our handler for accessibility click. Changelog: [Android][Fixed] Move selection to the end of the text input on accessibility click Reviewed By: mdvacca Differential Revision: D23441077 fbshipit-source-id: 16964f5b106637e55a98c6b0ef0f0041e8e6215d
1 parent 5fdb558 commit f0e80ae

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

ReactAndroid/src/androidTest/java/com/facebook/react/tests/TextInputTestCase.java

+31
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,37 @@ public void run() {
199199
assertFalse(reactEditText.isFocused());
200200
}
201201

202+
public void testAccessibilityFocus_notEmpty_selectionSetAtEnd() throws Throwable {
203+
String testId = "textInput1";
204+
String text = "Testing";
205+
206+
final ReactEditText reactEditText = getViewByTestId(testId);
207+
reactEditText.setText(text);
208+
runTestOnUiThread(
209+
new Runnable() {
210+
@Override
211+
public void run() {
212+
reactEditText.clearFocus();
213+
}
214+
});
215+
waitForBridgeAndUIIdle();
216+
assertFalse(reactEditText.isFocused());
217+
assertEquals(0, reactEditText.getSelectionStart());
218+
219+
runTestOnUiThread(
220+
new Runnable() {
221+
@Override
222+
public void run() {
223+
reactEditText.performAccessibilityAction(
224+
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
225+
reactEditText.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, null);
226+
}
227+
});
228+
waitForBridgeAndUIIdle();
229+
assertTrue(reactEditText.isFocused());
230+
assertEquals(text.length(), reactEditText.getSelectionStart());
231+
}
232+
202233
private void fireEditorActionAndCheckRecording(
203234
final ReactEditText reactEditText, final int actionId) throws Throwable {
204235
fireEditorActionAndCheckRecording(reactEditText, actionId, true);

ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java

+8
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ public ReactEditText(Context context) {
145145
@Override
146146
public boolean performAccessibilityAction(View host, int action, Bundle args) {
147147
if (action == AccessibilityNodeInfo.ACTION_CLICK) {
148+
int length = getText().length();
149+
if (length > 0) {
150+
// For some reason, when you swipe to focus on a text input that already has text in
151+
// it, it clears the selection and resets the cursor to the beginning of the input.
152+
// Since this is not typically (ever?) what you want, let's just explicitly set the
153+
// selection on accessibility click to undo that.
154+
setSelection(length);
155+
}
148156
return requestFocusInternal();
149157
}
150158
return super.performAccessibilityAction(host, action, args);

0 commit comments

Comments
 (0)