dewildte
04/21/2021, 7:16 PMAnimatedVisibilty
for pretty much everything.
But that composable does not have a callback, perhaps I could use a LaunchedEffect
or DisposableEffect
for that piece?
I am not sure if this is an architectural question or a compose question.
It’s kind of a cross cutting thing.Doris Liu
04/22/2021, 4:45 AMAnimatedVisibility
is to put a DisposableEffect
in its content
composable and rely on the onDisposed
callback. You could consider doing that.
Alternatively, if the enter/exit transition that you have for AnimatedVisibility
can be easily expressed via an animation as a part of the Transition
, (i.e. fading, sliding that doesn't depend on the size, etc) you can rewrite the animations and wait for the Transition
to finish all its animations.
Currently I'm working on an idea that allows AnimatedVisibility
to be created as a part of the Transition
: Transition<T>.AnimatedVisibility(visible: (T) -> Boolean, enter:.., exit:...)
. Seems like it would help accomplish what you are trying to do. 🙂 Sounds like you are building a sequential exit and then enter transition?dewildte
04/22/2021, 2:49 PMAnimatedVisiblity
and restructured the code to use the animateXAsState()
functions.
My main use case was screen transition choreography.Doris Liu
04/22/2021, 4:16 PMdewildte
04/22/2021, 4:18 PMDoris Liu
04/22/2021, 4:35 PMdewildte
04/22/2021, 5:50 PMdewildte
04/22/2021, 5:50 PMdewildte
04/22/2021, 5:57 PMdewildte
04/22/2021, 6:03 PMdewildte
04/22/2021, 6:05 PMDoris Liu
04/22/2021, 7:26 PMupdateTransition(transitionState: MutableTransitionState)
API? (API reference can be found here). With the MutableTransitionState
, you could skip the onShown
and onHidden
callbacks, as the animation will be updating that state for you. If you have more than one animation for each screen, I'd recommend trying out the Transition API. It should make things easier to manage if you had one transition for each screen, and adding all the enter/exit animations in that screen to the same transition.dewildte
04/22/2021, 8:33 PM// currentState will be updated to targetState when the transition is finished, so
// it can be used as a signal to start the next transition.
How do I do this? Do I used a LaunchedEffect
keyed on the current state?dewildte
04/22/2021, 8:37 PMLaunchedEffect(
key1 = state.currentState
) {
onTransitionCompleted(state.currentState)
}
Like this?Doris Liu
04/22/2021, 8:37 PMif(transitionState.currentState == transitionState.targetState && transitionState.currentState ==...) { // start another transition }
Doris Liu
04/22/2021, 8:38 PMcurrentState
itself is backed by a MutableState
, so if you read it in composition, you'll get a recomposition when it changes.Doris Liu
04/22/2021, 8:43 PMcurrentState
changes, you could create a snapShotFlow
, and collect from it. 🙂dewildte
04/22/2021, 8:50 PMdewildte
04/22/2021, 8:52 PMsnapShotFlow
!!!! mind blownDoris Liu
04/22/2021, 8:56 PMonTransitionCompleted
to the card, since you can observe that TransitionState
wherever you have a reference to it.dewildte
04/22/2021, 9:00 PMdewildte
04/22/2021, 9:05 PM@Composable
internal fun WindowFocusObserver(onWindowFocusChanged: (isWindowFocused: Boolean) -> Unit) {
val windowInfo = LocalWindowInfo.current
val callback = rememberUpdatedState(onWindowFocusChanged)
LaunchedEffect(windowInfo) {
snapshotFlow { windowInfo.isWindowFocused }.collect { callback.value(it) }
}
}
WindowInfo does it like this.Doris Liu
04/22/2021, 9:09 PMsnapshotFlow
.
You can consider creating the TransitionState
in the ViewModel, and derive other states from itdewildte
04/22/2021, 9:12 PMexcept you don’t really need pass theOk but I still need to pass some kind of callback into a Composable somewhere in order to get it called correct?to the cardonTransitionCompleted
dewildte
04/22/2021, 9:12 PMDoris Liu
04/22/2021, 9:14 PMOk but I still need to pass some kind of callback into a Composable somewhere in order to get it called correct?That's an imperative way of thinking. 😛 I'd declare the
text
as a derivedStateOf
the TransitionState
Doris Liu
04/22/2021, 9:15 PMDoris Liu
04/22/2021, 9:22 PMYou are just implying that it could be some higher up Composable?That's indeed what I was implying. 🙂 Though I often find the onFinished callback not necessary in Compose, especially if all it does is trigger another state change.
dewildte
04/22/2021, 9:30 PMdewildte
04/22/2021, 9:40 PMdata class ButtonUIState(
val text: State<String> = mutableStateOf(""),
val onClick: () -> Unit = {},
)
private val buttonState = ButtonUIState(
text = derivedStateOf { if (topBarState.isVisible.value) state2Text else state1Text },
onClick = ::transitionStates,
)
dewildte
04/22/2021, 9:51 PMval state = remember {
MutableTransitionState(false)
}
val text by remember {
derivedStateOf { if (state.currentState) "Lowered" else "Raised" }
}
val isEnabled by remember {
derivedStateOf { state.currentState == state.targetState }
}
Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.SpaceEvenly, horizontalAlignment = Alignment.CenterHorizontally) {
PoppingInCard(
state = state
)
Button(
onClick = { state.targetState = !state.currentState},
enabled = isEnabled
) {
Text(text = "Transition to $text")
}
}
Thanks to your help I think I am finally cooking with gas (maybe even jetpack fuel!)
This way the state can even be further hoisted into the model!Doris Liu
04/22/2021, 10:05 PM