AnimatedVisibilityScope
-
Cmn
interface AnimatedVisibilityScope
AnimatedContentScope |
Receiver scope for content lambda for AnimatedContent. |
AnimatedPaneScope |
Scope for the content of |
This is the scope for the content of AnimatedVisibility. In this scope, direct and indirect children of AnimatedVisibility will be able to define their own enter/exit transitions using the built-in options via Modifier.animateEnterExit. They will also be able define custom enter/exit animations using the transition object. AnimatedVisibility will ensure both custom and built-in enter/exit animations finish before it considers itself idle, and subsequently removes its content in the case of exit.
Note: Custom enter/exit animations that are created independent of the AnimatedVisibilityScope.transition will have no guarantee to finish when exiting, as AnimatedVisibility would have no visibility of such animations.
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibilityScope import androidx.compose.animation.EnterExitState import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.tween import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideIn import androidx.compose.animation.slideInVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp @OptIn(ExperimentalAnimationApi::class) @Composable fun AnimatedVisibilityScope.Item(modifier: Modifier, backgroundColor: Color) { // Creates a custom enter/exit animation for scale property. val scale by transition.animateFloat { enterExitState -> // Enter transition will be animating the scale from 0.9f to 1.0f // (i.e. PreEnter -> Visible). Exit transition will be from 1.0f to // 0.5f (i.e. Visible -> PostExit) when (enterExitState) { EnterExitState.PreEnter -> 0.9f EnterExitState.Visible -> 1.0f EnterExitState.PostExit -> 0.5f } } // Since we defined `Item` as an extension function on AnimatedVisibilityScope, we can use // the `animateEnterExit` modifier to produce an enter/exit animation for it. This will // run simultaneously with the `AnimatedVisibility`'s enter/exit. Box( modifier .fillMaxWidth() .padding(5.dp) .animateEnterExit( // Slide in from below, enter = slideInVertically(initialOffsetY = { it }), // No slide on the way out. So the exit animation will be scale (from the custom // scale animation defined above) and fade (from AnimatedVisibility) exit = ExitTransition.None, ) .graphicsLayer { scaleX = scale scaleY = scale } .clip(RoundedCornerShape(20.dp)) .background(backgroundColor) .fillMaxSize() ) { // Content of the item goes here... } } @Composable fun AnimateMainContent(mainContentVisible: MutableTransitionState<Boolean>) { Box { // Use the `MutableTransitionState<Boolean>` to specify whether AnimatedVisibility // should be visible. This will also allow AnimatedVisibility animation states to be // observed externally. AnimatedVisibility( visibleState = mainContentVisible, modifier = Modifier.fillMaxSize(), enter = fadeIn(), exit = fadeOut(), ) { Box { Column(Modifier.fillMaxSize()) { // We have created `Item`s below as extension functions on // AnimatedVisibilityScope in this example. So they can define their own // enter/exit to run alongside the enter/exit defined in AnimatedVisibility. Item(Modifier.weight(1f), backgroundColor = Color(0xffff6f69)) Item(Modifier.weight(1f), backgroundColor = Color(0xffffcc5c)) } // This FAB will be simply fading in/out as specified by the AnimatedVisibility FloatingActionButton( onClick = {}, modifier = Modifier.align(Alignment.BottomEnd).padding(20.dp), backgroundColor = MaterialTheme.colors.primary, ) { Icon(Icons.Default.Favorite, contentDescription = null) } } } // Here we can get a signal for when the Enter/Exit animation of the content above // has finished by inspecting the MutableTransitionState passed to the // AnimatedVisibility. This allows sequential animation after the enter/exit. AnimatedVisibility( // Once the main content is visible (i.e. targetState == true), and no pending // animations. We will start another enter animation sequentially. visible = mainContentVisible.targetState && mainContentVisible.isIdle, modifier = Modifier.align(Alignment.Center), enter = expandVertically(), exit = fadeOut(animationSpec = tween(50)), ) { Text("Transition Finished") } } }
Summary
Public functions |
||
|---|---|---|
open Modifier |
Modifier.animateEnterExit(
|
Cmn
|
Public properties |
||
|---|---|---|
Transition<EnterExitState> |
|
Cmn
|
Public functions
animateEnterExit
open fun Modifier.animateEnterExit(
enter: EnterTransition = fadeIn(),
exit: ExitTransition = fadeOut(),
label: String = "animateEnterExit"
): Modifier
animateEnterExit modifier can be used for any direct or indirect children of AnimatedVisibility to create a different enter/exit animation than what's specified in AnimatedVisibility. The visual effect of these children will be a combination of the AnimatedVisibility's animation and their own enter/exit animations.
enter and exit defines different EnterTransitions and ExitTransitions that will be used for the appearance and disappearance animation. There are 4 types of EnterTransition and ExitTransition: Fade, Expand/Shrink, Scale and Slide. The enter transitions can be combined using +. Same for exit transitions. The order of the combination does not matter, as the transition animations will start simultaneously. See EnterTransition and ExitTransition for details on the three types of transition.
By default, the enter transition will be a fadeIn of the content. And the exit transition will be fading out the content using fadeOut.
In some cases it may be desirable to have AnimatedVisibility apply no animation at all for enter and/or exit, such that children of AnimatedVisibility can each have their distinct animations. To achieve this, EnterTransition.None and/or ExitTransition.None can be used for AnimatedVisibility.
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideIn import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOut import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp @OptIn(ExperimentalAnimationApi::class) @Composable fun FullScreenNotification(visible: Boolean) { AnimatedVisibility(visible = visible, enter = fadeIn(), exit = fadeOut()) { // Fade in/out the background and foreground Box(Modifier.fillMaxSize().background(Color(0x88000000))) { Box( Modifier.align(Alignment.TopStart) .animateEnterExit( // Slide in/out the rounded rect enter = slideInVertically(), exit = slideOutVertically(), ) .clip(RoundedCornerShape(10.dp)) .requiredHeight(100.dp) .fillMaxWidth() .background(Color.White) ) { // Content of the notification goes here } } } }
Public properties
transition
val transition: Transition<EnterExitState>
transition allows custom enter/exit animations to be specified. It will run simultaneously with the built-in enter/exit transitions specified in AnimatedVisibility.