How can I set the cursor in a random position on a TextField when it it get focus?
The equivalent of editText.setSelection(position)
with the classic android view system.
This is the code I am using to have an edit text automatically receive the focus when it is added to the screen. I would like to be able to move the cursor from the default position which is 0
val (getText, setText) = remember { mutableStateOf("hello") }
AutofocusEditText(
text = getText,
setText = setText
)
...
@Composable
private fun AutofocusEditText(
text: String,
setText : (String) -> Unit
) {
val focusState = remember { mutableStateOf(FocusState.Inactive) }
val focusRequester = FocusRequester()
val focusModifier = Modifier.focus()
Row(
modifier = Modifier.focusObserver { newFocusValue -> focusState.value = newFocusValue }
) {
val focusRequesterModifier =
Modifier.focusRequester(focusRequester)
TextField(
value = text,
modifier = focusModifier.then(focusRequesterModifier),
backgroundColor = Color.Transparent,
onValueChange = setText,
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
onImeActionPerformed = { action, softKeyboardController ->
if (action == ImeAction.Done) {
softKeyboardController?.hideSoftwareKeyboard()
}
}
)
}
onActive {
focusRequester.requestFocus()
}
}
You have to use the TextFieldValue version of TextField.
@Composable
fun TextField(
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
/* ... */) {/* Impl */}
Code examples: EDIT: Compose Version 1.1.1 (13.04.22)
enum class CursorSelectionBehaviour {
START, END, SELECT_ALL
}
@Composable
fun AutofocusTextFieldExample(
initValue: String,
behaviour: CursorSelectionBehaviour = CursorSelectionBehaviour.END
) {
val direction = LocalLayoutDirection.current
var tfv by remember {
val selection = when (behaviour) {
CursorSelectionBehaviour.START -> {
if (direction == Ltr) TextRange.Zero else TextRange(initValue.length)
}
CursorSelectionBehaviour.END -> {
if (direction == Ltr) TextRange(initValue.length) else TextRange.Zero
}
CursorSelectionBehaviour.SELECT_ALL -> TextRange(0, initValue.length)
}
val textFieldValue = TextFieldValue(text = initValue, selection = selection)
mutableStateOf(textFieldValue)
}
val focusRequester = remember { FocusRequester.Default }
TextField(
modifier = Modifier.focusRequester(focusRequester),
value = tfv,
onValueChange = { tfv = it }
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}
OLD (04.01.21):
@Composable
fun AutoFocusingText() {
val textState = remember { mutableStateOf(TextFieldValue()) }
val focusState = remember { mutableStateOf(FocusState.Inactive) }
val focusRequester = FocusRequester()
val focusModifier = Modifier.focus()
Row(
modifier = Modifier.focusObserver { focusState.value = it }
) {
val focusRequesterModifier = Modifier.focusRequester(focusRequester)
TextField(
modifier = focusModifier.then(focusRequesterModifier),
value = textState.value,
onValueChange = { value: TextFieldValue ->
textState.value = value
}
)
}
onActive {
focusRequester.requestFocus()
}
}
If you have a non-empty string as an initial value you have to change the selection manually. Replace the empty TextFieldValue with: TextFieldValue(text = value, selection = TextRange(value.length, value.length))
When you want to extract the value like it is in your code. You either add the current selection as a parameter or extract it combined with the TextFieldValue. Otherwise, if the user edits in the middle of the text the cursor jumps back to the end on the next onValueChanged.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With