fix: select text on auto focus for TextInput (#45004)

Summary:
Fixes: https://github.com/facebook/react-native/issues/43413

This pull request addresses an issue on Android where the text selection was not working when both `selectTextOnFocus` and `autoFocus` were set to true on TextInput.
`ReactTextInputManager` was calling `setSelectAllOnFocus` on `ReactEditText` before its onLayout is called causing text selection to not work on auto focus.

Changes Made

- Added logic to wait for the ReactEditText view's layout to be drawn before attempting to select the text.
On the first layout pass, the code now explicitly calls selectAll() to select the text.
- Implemented a check to ensure selectAll() is only called during the first layout pass, avoiding unnecessary calls on subsequent layout passes.

Impact
This change ensures that text selection is properly triggered when selectTextOnFocus and autoFocus are both enabled, improving the user experience and making text input behavior consistent and reliable.

## Changelog:

[ANDROID] [FIXED]: fixed select text on auto focus for TextInput

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: https://github.com/facebook/react-native/pull/45004

Test Plan:
| Before | After |
|--------|--------|
| ![before](https://github.com/facebook/react-native/assets/61144478/02da975a-2c80-41b9-86c1-196d0324f437) | ![after](https://github.com/facebook/react-native/assets/61144478/fbe78758-04ab-460f-8ecb-b267ed07751a) |

Reviewed By: javache

Differential Revision: D59448600

Pulled By: cortinico

fbshipit-source-id: 8a594d3193f227ba2d64b808d905bab8b3d24e9b
This commit is contained in:
kunal.chavhan
2024-07-12 10:49:54 -07:00
committed by Facebook GitHub Bot
parent 44f8b08b8d
commit 18d6028ff9
4 changed files with 49 additions and 8 deletions
@@ -7725,6 +7725,7 @@ public class com/facebook/react/views/textinput/ReactEditText : androidx/appcomp
public fun setPlaceholder (Ljava/lang/String;)V
public fun setReturnKeyType (Ljava/lang/String;)V
public fun setScrollWatcher (Lcom/facebook/react/views/textinput/ScrollWatcher;)V
public fun setSelectTextOnFocus (Z)V
public fun setSelection (II)V
public fun setSelectionWatcher (Lcom/facebook/react/views/textinput/SelectionWatcher;)V
public fun setStateWrapper (Lcom/facebook/react/uimanager/StateWrapper;)V
@@ -120,6 +120,7 @@ public class ReactEditText extends AppCompatEditText {
private boolean mAutoFocus = false;
private boolean mContextMenuHidden = false;
private boolean mDidAttachToWindow = false;
private boolean mSelectTextOnFocus = false;
private @Nullable String mPlaceholder = null;
private final ReactViewBackgroundManager mReactBackgroundManager;
@@ -238,6 +239,12 @@ public class ReactEditText extends AppCompatEditText {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
onContentSizeChange();
if (mSelectTextOnFocus && isFocused()) {
// Explicitly call this method to select text when layout is drawn
selectAll();
// Prevent text on being selected for next layout pass
mSelectTextOnFocus = false;
}
}
@Override
@@ -1125,6 +1132,11 @@ public class ReactEditText extends AppCompatEditText {
mAutoFocus = autoFocus;
}
public void setSelectTextOnFocus(boolean selectTextOnFocus) {
super.setSelectAllOnFocus(selectTextOnFocus);
mSelectTextOnFocus = selectTextOnFocus;
}
public void setContextMenuHidden(boolean contextMenuHidden) {
mContextMenuHidden = contextMenuHidden;
}
@@ -655,7 +655,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
@ReactProp(name = "selectTextOnFocus", defaultBoolean = false)
public void setSelectTextOnFocus(ReactEditText view, boolean selectTextOnFocus) {
view.setSelectAllOnFocus(selectTextOnFocus);
view.setSelectTextOnFocus(selectTextOnFocus);
}
@ReactProp(name = ViewProps.COLOR, customType = "Color")
@@ -77,6 +77,39 @@ const styles = StyleSheet.create({
},
});
class AutoFocusWithSelectOnFocusTextExample extends React.Component<
$FlowFixMeProps,
any,
> {
constructor(props: any | void) {
super(props);
this.state = {
autoFocusFalse: 'autoFocus: false - selectTextOnFocus: true',
autoFocusTrue: 'autoFocus: true - selectTextOnFocus: true',
};
}
render(): React.Node {
return (
<View>
<ExampleTextInput
autoFocus={false}
selectTextOnFocus={true}
value={this.state.autoFocusFalse}
onChangeText={text => this.setState({autoFocusFalse: text})}
accessibilityLabel="I am the accessibility label for text input"
/>
<ExampleTextInput
autoFocus={true}
selectTextOnFocus={true}
value={this.state.autoFocusTrue}
onChangeText={text => this.setState({autoFocusTrue: text})}
accessibilityLabel="I am the accessibility label for text input"
/>
</View>
);
}
}
class WithLabel extends React.Component<$FlowFixMeProps> {
render(): React.Node {
return (
@@ -815,14 +848,9 @@ function MultilineStyledTextInput({
module.exports = ([
{
title: 'Auto-focus',
title: 'Auto-focus & select text on focus',
render: function (): React.Node {
return (
<ExampleTextInput
autoFocus={true}
accessibilityLabel="I am the accessibility label for text input"
/>
);
return <AutoFocusWithSelectOnFocusTextExample />;
},
},
{