How to change text field cursor position in jetpack compose
Asked Answered
C

4

39

I have list of text suggestions chip view above textfield, when user clicking chip I am appending the text into textfield. after that I want to move the cursor to the end position. I couldn't find solution for this in Jetpack compose. earlier we used editText.setSelection(position) to change cursor position in android views.

How to set a cursor position in jetpack compose Textfield?

         OutlinedTextField(
                    value = value,
                    onValueChange = { value = it },
                    maxLines = 8,
                    label = {
                        Text(
                            text = "Content",
                            maxLines = 1
                        )
                    },

                    modifier = Modifier
                        .fillMaxWidth()
                        .height(200.dp),
                    shape = RoundedCornerShape(2.dp),

                    )
Cakewalk answered 29/1, 2022 at 18:31 Comment(0)
C
53

We can use TextFieldValue to change cursor position

Initialise the TextFieldValue just like this

 var textFieldValueState by remember {
        mutableStateOf(
            TextFieldValue(
                text = ""
            )
        )
    }

after initialising it set the TextFieldValue just like the below

OutlinedTextField(
    value = textFieldValueState,
    onValueChange = { textFieldValueState = it },
    ...
    )

To append additional text and for cursor selection, follow these steps

IconButton(modifier = Modifier.then(Modifier.size(48.dp)),
     onClick = {
        val value = textFieldValueState.text.plus("****")
        textFieldValueState = TextFieldValue(
        text = value,
        selection = TextRange(value.length-2)
        )
     })

reference image

TextFieldValue text and selection variables are not changeable so we need to create new TextFieldValue to set the text and cursor position.

Chrome answered 29/1, 2022 at 19:10 Comment(1)
Don't work on FireTV.Seale
B
4

a "selection" should be used and TextFieldValue:

@Composable
fun CustomTextField() {
    val textState = remember { mutableStateOf(TextFieldValue(viewState.contextText)) }}
   val focusRequester = remember { FocusRequester() }

BasicTextField(
    value = textState.value,
    onValueChange = {
                textState.value = it
                viewModel.onContextText(it.text)
            }
    modifier = Modifier.focusRequester(focusRequester),
    textStyle = ...
)

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}

 // Set cursor position to the end when the text changes
DisposableEffect(Unit) {
    textState.value = textState.value.copy(
        selection = TextRange(textState.value.text.length)
    )
    onDispose { }
}
}
Byler answered 27/7, 2023 at 8:22 Comment(0)
C
3

An example of how to insert new text at the current position of the input cursor. And move the cursor to a new position

// TextField
var textFieldValue by remember { mutableStateOf(TextFieldValue("")) }
TextField(textFieldValue, onValueChange = { textFieldValue = it })

private fun insertText(textFieldValue: TextFieldValue, insertText: String): TextFieldValue {
    val maxChars = textFieldValue.text.length
    val textBeforeSelection = textFieldValue.getTextBeforeSelection(maxChars)
    val textAfterSelection = textFieldValue.getTextAfterSelection(maxChars)
    val newText = "$textBeforeSelection$insertText$textAfterSelection"
    val newCursorPosition = textBeforeSelection.length + insertText.length
    return TextFieldValue(
        text = newText,
        selection = TextRange(newCursorPosition)
    )
}

// use
onClick = { 
 textFieldValue = insertText(textFieldValue, " #$tag")
} 
Compel answered 7/6, 2023 at 11:41 Comment(1)
did'n work for meHemmer
Z
2
@Composable
fun MyScreen() {
    var textState by remember { mutableStateOf("Hello, world!") }
    val focusRequester = remember { FocusRequester() }
    Column(
        modifier = Modifier.padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        BasicTextField(
            value = TextFieldValue(textState, selection = TextRange(textState.length)),
            onValueChange = { textState = it.text },
            modifier = Modifier
                .fillMaxWidth()
                .focusRequester(focusRequester),
        )
        Button(
            onClick = {
                // Request focus and set the cursor at the end of the text when the button is clicked
                focusRequester.requestFocus()
            },
            modifier = Modifier.padding(top = 16.dp)
        ) {
            Text("Move Cursor to End")
        }
    }
}

val focusRequester = remember { FocusRequester() }: This line declares a FocusRequester object using the remember function. The FocusRequester is used to request focus on the BasicTextField programmatically.

when the button is clicked, it calls focusRequester.requestFocus() to request focus on the BasicTextField programmatically.

enter image description here

Zoan answered 28/7, 2023 at 8:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.