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

Vsevolod Kaganovych

01/11/2022, 4:39 PM
Does anyone know how to use
TextFieldValue
in
TextField
with
AnnotatedString
? Example: I have a
ViewModel
from where I observe state. When text changes, I update my state and create a new
AnnotatedString
like this
Copy code
val nokString = getNokString(amount = state.nokAmount)
the
getNokString()
looks like this
Copy code
@Composable
private fun getNokString(amount: String): AnnotatedString {
    return buildAnnotatedString {
        withStyle(
            style = SpanStyle(
                fontFamily = MaterialTheme.typography.subtitle1.fontFamily,
                fontSize = 40.sp
            )
        ) {
            append(amount.ifEmpty { "0" })
        }
        append(" ")
        withStyle(
            style = SpanStyle(
                fontFamily = MaterialTheme.typography.subtitle1.fontFamily,
                fontSize = 14.sp
            )
        ) {
            append("NOK")
        }
    }
}
But when I assign a new value to
TextField
Copy code
TextField(value = TextFieldValue(nokString),
          onValueChange = {
                 actioner.invoke(SendAction.OnNokChanged(it.text))
          })
The behaviour is unexpected: it appends the new result to the previous one. And I'm not sure how to handle this situation. Any ideas? Thanks in advance.
m

myanmarking

01/11/2022, 4:43 PM
i think you have to feed the the SAME TextFieldValue from the listener. Read the documentation on the listener, i think it explains that
v

Vsevolod Kaganovych

01/11/2022, 4:53 PM
I came up with this conclusion as well. But in this case how do I connect the value from
state
with the
TextFieldValue
instance? I need to update my state + generate a new value to
TextFieldValue
each time the text changes.
z

Zach Klippenstein (he/him) [MOD]

01/11/2022, 5:02 PM
The text field will give you the complete new string every time it changes, so you just need to make sure that finds it's way back into the text field call - how you do that is completely up to you.
v

Vsevolod Kaganovych

01/11/2022, 5:06 PM
Okay. So I definitely need help then. I want to just save the text into my state, nothing else. When the text changes, I get a new string, observe it and want the decorated string to be applied to the same instance of
TextFieldValue
. Any ideas how to achieve this?
So, I was able to achieve this with
VisualTransformation
. But this is really strange that I can't decorate string in runtime in TextField. The documentation is not quite clear about it.
r

Rick Regan

01/11/2022, 9:32 PM
What if you had something like
Copy code
var textFieldText by mutableStateOf("")
...
TextField(
    value = TextFieldValue(getNokString(textFieldText)),
    onValueChange = {
        textFieldText = it.text.replaceFirst(" NOK".toRegex(),"")
    }
)
You would strip away the annotation each time, including the " NOK" (but I'm not sure how you'd distinguish the 0 you added from one that is typed in the field).
13 Views