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

Miguel Coleto

09/21/2020, 8:21 AM
Hi! I'm having some difficulties to understand how my components are being recomposed. I'm making a simple dice roller app and I want to animate every dice every time I produce a new roll. The thing is that if a dice gets the same result as the previous roll it won't animate again. This is working as expected I suppose. But there are sometimes when a new result won't animate the dice again and this I don't understand. I'd like to fix that and force the animation even if the result is the same
There's a video of the described issue
Copy code
@Composable
fun Dice(
    number: DiceNumber,
    isEnabled: Boolean = true,
    modifier: Modifier = Modifier
) {
    val diceNumberDrawable = when (number) {
        DiceNumber.One -> R.drawable.dice_one
        DiceNumber.Two -> R.drawable.dice_two
        DiceNumber.Three -> R.drawable.dice_three
        DiceNumber.Four -> R.drawable.dice_four
        DiceNumber.Five -> R.drawable.dice_five
        DiceNumber.Six -> R.drawable.dice_six
    }.run { vectorResource(id = this) }

    val rotation = animatedFloat(0f)
    val randomSpins = remember(number.value) { Random.nextInt(2, 4) }
    val randomDuration = remember(number.value) { Random.nextInt(600, 1200) }
    rotation.animateTo(
        targetValue = 360f * randomSpins,
        anim = tween(
            durationMillis = randomDuration,
            easing = CubicBezierEasing(0.3f, 0.9f, 1f, 1f)
        )
    )

    Image(
        asset = diceNumberDrawable,
        alpha = if (isEnabled) 1f else 0.4f,
        modifier = modifier
            .size(80.dp)
            .drawLayer(rotationZ = rotation.value)
    )
}
y

Yann Badoual

09/21/2020, 8:26 AM
You could use an
Int
that you increment each time you press the roll button. And use this int as a key to the
remember
calls instead of
number.value
. This way each roll will reset the value remembered and should re-trigger the
animateTo
call
m

Miguel Coleto

09/21/2020, 8:33 AM
Makes sense, I'll try 👌
I've tried to pass the seed I use for generating a Random object for remembering it but the behavior is still the same :/
t

Timo Drick

09/24/2020, 12:31 AM
I do not really understand your DiceNumber system. But my guess is that this DiceNumber class confuses compose and compose is not able to associate the different composables each time you do a new roll. You could add in DiceDrawer.kt:31
Copy code
chunk.forEach { number ->
    key(number) {
        Dice(
            number = number,
            isEnabled = number.value >= minimumResult,
            modifier = Modifier.weight(1f)
        )
    }
}
But in theory this should not be necessary.
m

Miguel Coleto

09/24/2020, 5:49 AM
The dice number class is an attempt to strongly type the restriction of dice results. I'll try to simplify and see what happens
t

Timo Drick

09/24/2020, 1:34 PM
When you add this key(number) all dices will roll every time
m

Miguel Coleto

09/24/2020, 4:28 PM
Should this be done for every list, even if they are not for dices like this one? React forces you to use unique keys in lists
t

Timo Drick

09/24/2020, 4:42 PM
No also i found out that when you use this key the savedinstanceState thing is not working as expected. So better to not use this.
👍 1
5 Views