So I'm trying to do a simple app that changes the color to red or green and goes back to black if a price fluctuates, my currently implementation is this
@Composable
fun LaunchingComposable() {
var coinPrice by remember {
mutableStateOf(2000.30)
}
CoinHeader(modifier = Modifier.padding(horizontal = 8.dp),
"http://myicon.com/image.png",
coinPrice
)
LaunchedEffect(Unit) {
delay(3000)
coinPrice = 2000.40
delay(3000)
coinPrice = 2000.20
delay(3000)
coinPrice = 2000.10
delay(3000)
coinPrice = 2000.20
}
}
...
@Composable
fun CoinHeader(modifier: Modifier, coinImageUrl: String, currentPrice: Double) {
val baseColor = remember { Animatable(Black) }
val previousPrice = remember {
currentPrice
}
Row(
modifier = modifier,
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
modifier = Modifier
.width(30.dp)
.height(30.dp)
.padding(end = 4.dp)
.data(coinImageUrl)
.build()
)
LaunchedEffect(currentPrice) {
if (previousPrice < currentPrice) {
baseColor.animateTo(Red, animationSpec = tween(1000))
} else {
baseColor.animateTo(Green, animationSpec = tween(1000))
}
baseColor.animateTo(Black, animationSpec = tween(1000))
}
Text(text = currentPrice.toPrice(), color = baseColor.targetValue)
}
}
In my last composable I'm expecting the values to change to Green - Red - Red - Green
I need to always store previous value of my coinPrice in order to compare it, do a fade animation with the color and then come back to the black color.
Currently this is my output
The problems are 2
- Fade in - out color from red to black or green to black not happening
- Seems like it always compare with the first value
Can anyone explain to me why if I recompose after coinPrice has been changed, the value of previous is not set correctly ?
CodePudding user response:
Your current implementation of previousPrice
is really just original price because it is never changed. You never set it to a new value, so it forever holds the first currentPrice
ever received. Your remember
call doesn't even have a key, so it will never recompute it, but even if you did, there would be no way to compute it to be the previous value instead of the current one.
I think you will have to use a mutable wrapper class around the remembered previous price so you can actually change it. An array may suffice, or you could write a specific data class to wrap a var
.
Something like this:
val rememberedPreviousPrice = remember { arrayOf(currentPrice) }
val previousPrice = rememberedPreviousPrice[0]
rememberedPreviousPrice[0] = currentPrice
Secondly, you're using baseColor.targetValue
instead of baseColor.value
, so it's not using the animated value, but jumping right to the final ("target") color.
There could be other problems in your code. I'm not sure because I haven't done much with LaunchedEffects or animations in Compose yet myself.
By the way, you should not use Double for currency. Use BigDecimal instead. Read here and here.