https://kotlinlang.org logo
g

Guy Bieber

09/30/2020, 8:56 PM
The example of rotation in the jetpack compose playground seems a bit messy. Is there a simpler method to rotate a @Composable?
v

Vinay Gaba

09/30/2020, 9:35 PM
what was it using in the example?
g

Guy Bieber

09/30/2020, 10:00 PM
Copy code
@Composable
fun RepeatedRotationDemo() {
    val state = remember { mutableStateOf(RotationStates.Original) }
    Column(
        Modifier.fillMaxSize()
            .wrapContentSize(Alignment.Center),
        verticalArrangement = Arrangement.SpaceEvenly
    ) {
        val textStyle = TextStyle(fontSize = 18.sp)
        Text(
            modifier = Modifier.tapGestureFilter(onTap = { state.value = RotationStates.Rotated }),
            text = "Rotate 10 times",
            style = textStyle
        )
        Text(
            modifier = Modifier.tapGestureFilter(onTap = { state.value = RotationStates.Original }),
            text = "Reset",
            style = textStyle
        )
        val transitionState = transition(
            definition = definition,
            toState = state.value
        )
        Canvas(Modifier.preferredSize(100.dp)) {
            rotate(transitionState[rotation], 0.0f, 0.0f) {
                drawRect(Color(0xFF00FF00))
            }
        }
    }
}

private enum class RotationStates {
    Original,
    Rotated
}

private val rotation = FloatPropKey()

private val definition = transitionDefinition<RotationStates> {
    state(RotationStates.Original) {
        this[rotation] = 0f
    }
    state(RotationStates.Rotated) {
        this[rotation] = 360f
    }
    transition(RotationStates.Original to RotationStates.Rotated) {
        rotation using repeatable(
            iterations = 10,
            animation = tween(
                easing = LinearEasing,
                durationMillis = 1000
            )
        )
    }
    transition(RotationStates.Rotated to RotationStates.Original) {
        rotation using tween(
            durationMillis = 300
        )
    }
}
It would be lovely to have something like this: Rotate ( duration : Long, step : Float) { Image () … }
v

Vinay Gaba

09/30/2020, 10:07 PM
oh you can totally just use the logic from your first message and create a composable that makes the API look exactly like your second message 😄
💯 1
g

Guy Bieber

09/30/2020, 10:21 PM
When I tried it the rotate could not take a @Composable
Copy code
@Composable
fun Rotate ( durationMillis : Int, rotations : Int, children: @Composable() () -> kotlin.Unit) {
    val state = remember { mutableStateOf(RotationStates.Original) }
    val rotation = FloatPropKey()
    val definition = transitionDefinition<RotationStates> {
        state(RotationStates.Original) {
            this[rotation] = 0f
        }
        state(RotationStates.Rotated) {
            this[rotation] = 360f
        }
        transition(RotationStates.Original to RotationStates.Rotated) {
            rotation using repeatable(
                iterations = rotations,
                animation = tween(
                    easing = LinearEasing,
                    durationMillis = durationMillis
                )
            )
        }
        transition(RotationStates.Rotated to RotationStates.Original) {
            rotation using tween(
                durationMillis = durationMillis
            )
        }
    }
    val transitionState = transition(
        definition = definition,
        toState = state.value
    )
    Canvas(Modifier.preferredSize(100.dp)) {
        rotate(transitionState[rotation], 0.0f, 0.0f) {
            children()
        }
    }
}
@Composable invocations can only happen from the context of a @Composable function
Is there a version of rotate that is composable?
it really should be a modifier like animateContentSize.
grrrr
v

Vinay Gaba

09/30/2020, 11:05 PM
replace the
Canvas
with a
Box
and you can then use this
Copy code
Modifier.drawLayer(rotationZ = transitionState[rotation])
g

Guy Bieber

09/30/2020, 11:23 PM
Hmmm. Tried that it compiles and runs, but no rotation:
Copy code
private enum class RotationStates {
        Original,
        Rotated
    }
    
    @Composable
    fun Rotate ( durationMillis : Int, rotations : Int, children: @Composable() () -> kotlin.Unit) {
        val state = remember { mutableStateOf(RotationStates.Original) }
        val rotation = FloatPropKey()
        val definition = transitionDefinition<RotationStates> {
            state(RotationStates.Original) {
                this[rotation] = 0f
            }
            state(RotationStates.Rotated) {
                this[rotation] = 360f
            }
            transition(RotationStates.Original to RotationStates.Rotated) {
                rotation using repeatable(
                    iterations = rotations,
                    animation = tween(
                        easing = LinearEasing,
                        durationMillis = durationMillis
                    )
                )
            }
            transition(RotationStates.Rotated to RotationStates.Original) {
                rotation using tween(
                    durationMillis = durationMillis
                )
            }
        }
        if (state.value == RotationStates.Original) {
            state.value = RotationStates.Rotated
        } else {
            state.value = RotationStates.Original
        }
        val transitionState = transition(
            definition = definition,
            toState = state.value
        )
        Box (
            Modifier.drawLayer(rotationZ = transitionState[rotation],)
        ) {
            children()
        }
    }
v

Vinay Gaba

09/30/2020, 11:54 PM
use this as a base for your rotation logic and replace the canvas in that example with
Copy code
Box(
        modifier = Modifier.fillMaxSize()
            .drawLayer(rotationZ = state[rotation]),
        gravity = ContentGravity.Center,
    ) {
        children()
    }
👍 1

https://github.com/vinaygaba/Learn-Jetpack-Compose-By-Example/raw/master/screenshots/animation_rotation.gif

👍 2
2 Views