https://kotlinlang.org logo
#compose
Title
# compose
n

Nacho Ruiz Martin

03/20/2023, 8:27 AM
Hey 👋 I have a ViewModel which has a
StateFlow<String>
. This flow is collected inside a Composable with
.collectAsState(Dispatchers.Main.immediate)
. The string inside is used as the value of a
BasicTextField
and the ViewModel has a function to update this value in the state. All goes as expected if the user is the one typing on the keyboard 👍 but, if a button is pressed on the interface, the value of the text field should be cleared a new value should be added as some kind of prefix (editable by the user, just as a helper). When I add this value in the ViewModel, the cursor of the text field stays at the beginning instead of moving to the end of the text. I have read this article: https://medium.com/androiddevelopers/effective-state-management-for-textfield-in-compose-d6e5b070fbe5. But I thought with
Dispatchers.Main.immediate
it should be all good? Thanks for the help.
a

Albert Chang

03/20/2023, 9:32 AM
Use
TextFieldValue
instead of
String
and use
TextFieldValue(text = newString, selection = TextRange(newString.length))
when you replace the text.
n

Nacho Ruiz Martin

03/20/2023, 10:36 AM
I can’t actually because the ViewModel is done on KMP so no
TextFieldValue
there. I can store the string and the range separately, though, but I would like to delegate it to the OS. Is it expected that the cursor is kept at the beginning in this situation?
a

Albert Chang

03/20/2023, 10:36 AM
Yes.
n

Nacho Ruiz Martin

03/20/2023, 10:37 AM
It’s certainly unexpected given that pasting or inserting a suggestion in the keyboard makes the cursor move as expected.
a

Albert Chang

03/20/2023, 10:45 AM
It's because you are clearing the text once, which resets the cursor position.
n

Nacho Ruiz Martin

03/20/2023, 10:47 AM
When I said “clear” I meant just send the prefix to the text field, instead of the previous value + the prefix. Meaning that if the user wrote “hello world” in the text field, when the button is clicked, the text field will contain “@handle “, for example.
a

Albert Chang

03/20/2023, 10:49 AM
When you change the text (of the
String
overload), the cursor will be kept at its original position, unless the new text is shorter than cursor position, in which case the cursor will be moved to the end of the text.
n

Nacho Ruiz Martin

03/20/2023, 10:51 AM
But it does behave differently when you use the keyboard suggestions, for example. So the component is internally doing something with that, right?
Anyway, at least I know why it’s happening. Thanks! 👍 I will store the desired cursor position in the screen state.
a

Albert Chang

03/20/2023, 10:58 AM
Text field only uses
TextFieldValue
as state internally, and keyboard input will trigger updates of both
text
and
selection
(and potentially
composition
). The overload that takes
String
is just a wrapper that synchronizes the external
String
and the text of internal
TextFieldValue
.
n

Nacho Ruiz Martin

03/20/2023, 10:59 AM
Ok, that sounds reasonable, thanks.
z

Zach Klippenstein (he/him) [MOD]

03/21/2023, 3:30 PM
TextFieldValue
does support multiplatform, although unfortunately not kotlin/native yet.
73 Views