Skip to content

Commit

Permalink
EditText: maintain cursor position when text changes
Browse files Browse the repository at this point in the history
Summary:
Similar to D29786190 (b0e39b2) on iOS, keeps cursor position constant to the end of the text whenever text changes without selection updates.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D29879663

fbshipit-source-id: da1b50a99ae3b9ef796423146ba49e4172e286df
  • Loading branch information
Andrei Shikov authored and facebook-github-bot committed Jul 23, 2021
1 parent efb359f commit de44184
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,20 @@ public void maybeSetSelection(int eventCounter, int start, int end) {
}

if (start != UNSET && end != UNSET) {
// clamp selection values for safety
start = clampToTextLength(start);
end = clampToTextLength(end);

setSelection(start, end);
}
}

private int clampToTextLength(int value) {
int textLength = getText() == null ? 0 : getText().length();

return Math.max(0, Math.min(value, textLength));
}

@Override
public void setSelection(int start, int end) {
if (DEBUG_MODE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,22 @@ public void updateExtraData(ReactEditText view, Object extraData) {
Spannable spannable = update.getText();
TextInlineImageSpan.possiblyUpdateInlineImageSpans(spannable, view);
}

// Ensure that selection is handled correctly on text update
boolean isCurrentSelectionEmpty = view.getSelectionStart() == view.getSelectionEnd();
int selectionStart = update.getSelectionStart();
int selectionEnd = update.getSelectionEnd();
if ((selectionStart == UNSET || selectionEnd == UNSET) && isCurrentSelectionEmpty) {
// if selection is not set by state, shift current selection to ensure constant gap to
// text end
int textLength = view.getText() == null ? 0 : view.getText().length();
int selectionOffset = textLength - view.getSelectionStart();
selectionStart = update.getText().length() - selectionOffset;
selectionEnd = selectionStart;
}

view.maybeSetTextFromState(update);
view.maybeSetSelection(
update.getJsEventCounter(), update.getSelectionStart(), update.getSelectionEnd());
view.maybeSetSelection(update.getJsEventCounter(), selectionStart, selectionEnd);
}
}

Expand Down

0 comments on commit de44184

Please sign in to comment.