Skip to content

Commit e6a844d

Browse files
idoyanaclaude
andcommitted
fix: show soft keyboard when long-press starts text selection in TextInput on Android
ReactEditText marks itself textIsSelectable in onAttachedToWindow (a removeClippedSubviews workaround, #6805), which makes the platform Editor treat every RN TextInput as read-only selectable text and skip its "Show the IME to be able to replace text" branch when a selection action mode starts (Editor#startActionModeInternal gates that branch on !isTextSelectable()). RN's own keyboard paths only cover clicks and programmatic focus, so long-pressing to select text in an unfocused input — or in a focused input after the keyboard was dismissed — left the user with a selection toolbar and no keyboard. Compensate in ReactEditText: request the keyboard when a selection or insertion action mode is created, and when focus is gained with a non-collapsed selection (the action mode can precede focus). Guarded by isEnabled (the editable prop), isInTouchMode, and showSoftInputOnFocus, mirroring both requestFocusProgrammatically() and the platform branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 0015d1e commit e6a844d

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

  • packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,13 @@ public open class ReactEditText public constructor(context: Context) : AppCompat
258258
if (contextMenuHidden) {
259259
return false
260260
}
261+
// setTextIsSelectable(true) (see onAttachedToWindow) makes the platform Editor
262+
// treat this view as read-only selectable text and skip its "Show the IME to be
263+
// able to replace text" branch when a selection or insertion action mode starts
264+
// (Editor#startActionModeInternal gates it on !isTextSelectable()). Compensate
265+
// here so long-pressing an editable input summons the keyboard, matching stock
266+
// EditText behavior.
267+
showSoftKeyboardIfEditable()
261268
menu.removeItem(android.R.id.pasteAsPlainText)
262269
return true
263270
}
@@ -499,6 +506,14 @@ public open class ReactEditText public constructor(context: Context) : AppCompat
499506
if (focused && selectionWatcher != null) {
500507
selectionWatcher?.onSelectionChanged(selectionStart, selectionEnd)
501508
}
509+
// Gaining focus with a non-collapsed selection means focus arrived through a
510+
// long-press text selection rather than a tap or programmatic focus — the one focus
511+
// path that never requests the soft keyboard (see onCreateActionMode). The action
512+
// mode can be created before this view becomes the IME-served view, so request the
513+
// keyboard again now that focus has landed.
514+
if (focused && hasSelection()) {
515+
showSoftKeyboardIfEditable()
516+
}
502517
}
503518

504519
internal fun setSelectionWatcher(selectionWatcher: SelectionWatcher?) {
@@ -909,6 +924,14 @@ public open class ReactEditText public constructor(context: Context) : AppCompat
909924

910925
protected fun showSoftKeyboard(): Boolean = inputMethodManager.showSoftInput(this, 0)
911926

927+
// Mirrors the guard on requestFocusProgrammatically(), plus editability ("editable"
928+
// prop maps to isEnabled): never summon the keyboard for a read-only input.
929+
private fun showSoftKeyboardIfEditable() {
930+
if (isEnabled && isInTouchMode && showSoftInputOnFocus) {
931+
showSoftKeyboard()
932+
}
933+
}
934+
912935
protected fun hideSoftKeyboard() {
913936
inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
914937
}

0 commit comments

Comments
 (0)