'What's the use of `MutableTransitionState`? Looks like mutableStateOf does all it can equally good
In https://developer.android.com/jetpack/compose/animation, it is mentioned that
We sometimes want to have an initial state different from the first target state. We can use updateTransition with MutableTransitionState to achieve this. For example, it allows us to start animation as soon as the code enters composition.
// Start in collapsed state and immediately animate to expanded
var currentState = remember { MutableTransitionState(BoxState.Collapsed) }
currentState.targetState = BoxState.Expanded
val transition = updateTransition(currentState)
// ...
(For full code, refer to full code example 1. below)
However, the above code is only working for initial animation but not subsequent (i.e. change from Expanded to Collapsed), as whenever the currentState.targetState changes, the composable function will run and retriggered currentState.targetState = BoxState.Expanded.
To fix the problem, I'll have to
var currentState by remember { mutableStateOf(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "")
LaunchedEffect(Unit) {
currentState.targetState = BoxState.Expanded
}
(For full code, refer to full code example 2. below)
This will make the animation start automatically from Collapsed to Expanded. Also subsequently upon change from Expanded to Collapse (e.g. through a button click), it will still work, as the LaunchedEffect is no longer triggered.
With the LaunchedEffect, we can also do it with normal mutableStateOf, i.e. without MutableTransitionState, and still, behave well.
var currentState by remember { mutableStateOf(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "")
LaunchedEffect(Unit) {
currentState = BoxState.Expanded
}
(For full code, refer to full code example 3. below)
So I cannot see any extra benefit using MutableTransitionState compare to the normal mutableStateOf. Anything I miss?
Full Code that describes the situation above
1. MutableTransitionState code follow document example that doesn't work
The code that doesn't works with just MutableTransitionState (i.e. no effect on button click, only having initial animation)
@Composable
fun Greeting() {
val currentState = remember { MutableTransitionState(BoxState.Collapsed) }
currentState.targetState = BoxState.Expanded
val transition = updateTransition(currentState, label = "")
val rect by transition.animateRect(label = "") { state ->
when (state) {
BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f)
BoxState.Expanded -> Rect(100f, 100f, 300f, 300f)
}
}
Column {
Canvas(
modifier = Modifier.fillMaxWidth().height(500.dp)
.border(BorderStroke(1.dp, Color.Green))
) {
drawPath(Path().apply { addRect(rect) }, Color.Red)
}
Button(onClick = {
currentState.targetState =
if (currentState.targetState == BoxState.Expanded) BoxState.Collapsed
else BoxState.Expanded
}) {
Text("Click Me")
}
}
}
2. MutableTransitionState code with launched effect that works
The code that works with just MutableTransitionState (i.e. have effect on button click, and having initial animation)
@Composable
fun Greeting() {
val currentState = remember { MutableTransitionState(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "")
val rect by transition.animateRect(label = "") { state ->
when (state) {
BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f)
BoxState.Expanded -> Rect(100f, 100f, 300f, 300f)
}
}
Column {
Canvas(
modifier = Modifier.fillMaxWidth().height(500.dp)
.border(BorderStroke(1.dp, Color.Green))
) {
drawPath(Path().apply { addRect(rect) }, Color.Red)
}
Button(onClick = {
currentState.targetState =
if (currentState.targetState == BoxState.Expanded) BoxState.Collapsed
else BoxState.Expanded
}) {
Text("Click Me")
}
}
LaunchedEffect(Unit) {
currentState.targetState = BoxState.Expanded
}
}
3. Just mutableStateOf code with launched effect that still works
The code that works with just mutableStateOf (i.e. have effect on button click, and having initial animation)
@Composable
fun Greeting() {
var currentState by remember { mutableStateOf(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "")
val rect by transition.animateRect(label = "") { state ->
when (state) {
BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f)
BoxState.Expanded -> Rect(100f, 100f, 300f, 300f)
}
}
Column {
Canvas(
modifier = Modifier.fillMaxWidth().height(500.dp)
.border(BorderStroke(1.dp, Color.Green))
) {
drawPath(Path().apply { addRect(rect) }, Color.Red)
}
Button(onClick = {
currentState =
if (currentState == BoxState.Expanded) BoxState.Collapsed
else BoxState.Expanded
}) {
Text("Click Me")
}
}
LaunchedEffect(Unit) {
currentState = BoxState.Expanded
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
