rememberTransition
Functions summary
Transition<T> |
@ComposableCreates a |
Cmn
|
Functions
rememberTransition
@Composable
fun <T : Any?> rememberTransition(
transitionState: TransitionState<T>,
label: String? = null
): Transition<T>
Creates a Transition and puts it in the currentState of the provided transitionState. If the TransitionState.targetState changes, the Transition will change where it will animate to.
Remember: The provided transitionState needs to be remembered.
Compared to updateTransition that takes a targetState, this function supports a different initial state than the first targetState. Here is an example:
import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateDp import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.rememberTransition import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.material.Card import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp // This composable enters the composition with a custom enter transition. This is achieved by // defining a different initialState than the first target state using `MutableTransitionState` @Composable fun PoppingInCard() { // Creates a transition state with an initial state where visible = false val visibleState = remember { MutableTransitionState(false) } // Sets the target state of the transition state to true. As it's different than the initial // state, a transition from not visible to visible will be triggered. visibleState.targetState = true // Creates a transition with the transition state created above. val transition = rememberTransition(visibleState) // Adds a scale animation to the transition to scale the card up when transitioning in. val scale by transition.animateFloat( // Uses a custom spring for the transition. transitionSpec = { spring(dampingRatio = Spring.DampingRatioMediumBouncy) } ) { visible -> if (visible) 1f else 0.8f } // Adds an elevation animation that animates the dp value of the animation. val elevation by transition.animateDp( // Uses a tween animation transitionSpec = { // Uses different animations for when animating from visible to not visible, and // the other way around if (false isTransitioningTo true) { tween(1000) } else { spring() } } ) { visible -> if (visible) 10.dp else 0.dp } Card( Modifier.graphicsLayer(scaleX = scale, scaleY = scale) .size(200.dp, 100.dp) .fillMaxWidth(), elevation = elevation, ) {} }
In most cases, it is recommended to reuse the same transitionState that is remembered, such that Transition preserves continuity when targetState is changed. However, in some rare cases it is more critical to immediately snap to a state change (e.g. in response to a user interaction). This can be achieved by creating a new transitionState:
import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.keyframes import androidx.compose.animation.core.rememberTransition import androidx.compose.animation.core.snap import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.Icon import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput // enum class LikedStates { Initial, Liked, Disappeared } @Composable fun doubleTapToLike() { // Creates a transition state that starts in [Disappeared] State var transitionState by remember { mutableStateOf(MutableTransitionState(LikedStates.Disappeared)) } Box( Modifier.fillMaxSize().pointerInput(Unit) { detectTapGestures( onDoubleTap = { // This creates a new `MutableTransitionState` object. When a new // `MutableTransitionState` object gets passed to `updateTransition`, a // new transition will be created. All existing values, velocities will // be lost as a result. Hence, in most cases, this is not recommended. // The exception is when it's more important to respond immediately to // user interaction than preserving continuity. transitionState = MutableTransitionState(LikedStates.Initial) } ) } ) { // This ensures sequential states: Initial -> Liked -> Disappeared if (transitionState.currentState == LikedStates.Initial) { transitionState.targetState = LikedStates.Liked } else if (transitionState.currentState == LikedStates.Liked) { // currentState will be updated to targetState when the transition is finished, so // it can be used as a signal to start the next transition. transitionState.targetState = LikedStates.Disappeared } // Creates a transition using the TransitionState object that gets recreated at each // double tap. val transition = rememberTransition(transitionState) // Creates an alpha animation, as a part of the transition. val alpha by transition.animateFloat( transitionSpec = { when { // Uses different animation specs for transitioning from/to different // states LikedStates.Initial isTransitioningTo LikedStates.Liked -> keyframes { durationMillis = 500 0f at 0 // optional 0.5f at 100 1f at 225 // optional } LikedStates.Liked isTransitioningTo LikedStates.Disappeared -> tween(durationMillis = 200) else -> snap() } } ) { if (it == LikedStates.Liked) 1f else 0f } // Creates a scale animation, as a part of the transition val scale by transition.animateFloat( transitionSpec = { when { // Uses different animation specs for transitioning from/to different // states LikedStates.Initial isTransitioningTo LikedStates.Liked -> spring(dampingRatio = Spring.DampingRatioHighBouncy) LikedStates.Liked isTransitioningTo LikedStates.Disappeared -> tween(200) else -> snap() } } ) { when (it) { LikedStates.Initial -> 0f LikedStates.Liked -> 4f LikedStates.Disappeared -> 2f } } Icon( Icons.Filled.Favorite, "Like", Modifier.align(Alignment.Center) .graphicsLayer(alpha = alpha, scaleX = scale, scaleY = scale), tint = Color.Red, ) } }