user13267
user13267

Reputation: 7193

Is there a way to dynamically change the string in Text() of compose?

For example, after some modification to the sample code snippet given in android developer's site

@Composable
fun ClickCounter(clicks: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("I've been clicked $clicks times")
    }
}  

it is possible to count the number of times a button is pressed and display this count by changing the string in the Text component in the UI. However this needs the user to physically press the button to get Text to change. Is there a way to do this programmatically? I would like to perform some calculation and somewhere else and when the result is ready, display it by updating Text (doing something like Text.setText("...") had I been using xml to generate the UI). How do I change the value of Text programmatically? Do any of the jetpack compose sample programs from google have a simple example of this?

Upvotes: 14

Views: 21564

Answers (4)

R M Vivek
R M Vivek

Reputation: 54

    var wishMessage by remember { mutableStateOf(getDay()) }
    Row{ Text(text = wishMessage) }
     

private fun getDay():String
{
    var wishMessage = "Good Morning"
    val c = Calendar.getInstance()
    val timeOfDay = c.get(Calendar.HOUR_OF_DAY)
    if (timeOfDay >= 0 && timeOfDay < 12) {
        wishMessage="Good Morning"
    } else if (timeOfDay >= 12 && timeOfDay < 16) {
        wishMessage="Good Afternoon"
    } else if (timeOfDay >= 16 && timeOfDay < 21) {
        wishMessage="Good Evening"
    } else if (timeOfDay >= 21 && timeOfDay < 24) {
        wishMessage="Good Night"
    }
    return wishMessage
}

Upvotes: 0

Gabriele Mariotti
Gabriele Mariotti

Reputation: 365028

In Compose the UI is immutable and there's no way to update it after it's been drawn but you can control the state of your UI.

In other word you don't have a method like Text.setText("...") but you can build composables functions that work on state and events.

enter image description here

For example you can use mutableStateOf(value).
It creates a MutableState, which is an observable type in Compose. Any changes to its value will schedule recomposition of any composable functions that read that value.

You can use something like:

    var count by remember { mutableStateOf(0) }                        
    Button(onClick = { count++ }){
                Text("Add")
    }
    Text(text = "count: ${count}")

More info here.

Upvotes: 5

Jaxx0rr
Jaxx0rr

Reputation: 595

same answer as Sinner but without the riddle

class MainActivity : ComponentActivity() {

    private val dyntext = mutableStateOf("")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        dyntext.value = "OK"

        setContent {
            ShowText()
        }

    }

    @Composable
    fun ShowText() {
        val dynt by dyntext
        Text(dynt)
    }
}

Upvotes: 5

Sinner of the System
Sinner of the System

Reputation: 2966

composable functions need to have a MutableState in order to be programmatically updated. It can be created from an observable (like LiveData or Flow) or by calling mutableStateOf().

val text = mutableStateOf("text")
// or
val text = MutableStateFlow("text")

@Composable
fun MyText() {
    val myText by text
    // or
    val myText by text.collectAsState()
    Text(myText)
}

then you can update the value programmatically by updating the observable:

text.value = "other text"

Example

class MainActivity : AppCompatActivity() {
    private val a = 10000L
    private val b = 1000L
    private val c = mutableStateOf(a)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val timer = object : CountDownTimer(a, b) {
            override fun onTick(millisUntilFinished: Long) {
                Log.d("MYLOG", "text updated programmatically")
                c.value = millisUntilFinished
            }

            override fun onFinish() {
                c.value = 0
            }
        }
        timer.start()
        setContent { CountDown() }
    }

    @Composable
    fun CountDown() {
        val milliseconds by c
        val text = (milliseconds / 1000).toString()
        Text(text)
    }
}

Read more here

Upvotes: 18

Related Questions