Home > Net >  Color is not changed correctly after state change
Color is not changed correctly after state change

Time:01-23

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

enter image description here

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.

  • Related