blob: f21892fc2680597ad44e1f7e78b0823e2abe32cc [file] [log] [blame]
<html devsite="true">
<head>
<title>ExitTransition</title>
{% setvar book_path %}/reference/kotlin/androidx/_book.yaml{% endsetvar %}
{% include "_shared/_reference-head-tags.html" %}
</head>
<body>
<h1>ExitTransition</h1>
<p>
<pre>@<a href="/reference/kotlin/androidx/compose/animation/ExperimentalAnimationApi.html">ExperimentalAnimationApi</a> sealed class ExitTransition</pre>
</p>
<hr>
<p><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> defines how an <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code> Composable disappears on screen as it becomes not visible. The 3 categories of <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> available are:</p>
<ol>
<li>
<p>fade: <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#fadeOut(kotlin.Float,androidx.compose.animation.core.FiniteAnimationSpec)">fadeOut</a></code></p>
</li>
<li>
<p>slide: <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOut(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOut</a></code>, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOutHorizontally(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOutHorizontally</a></code>, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOutVertically(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOutVertically</a></code></p>
</li>
<li>
<p>shrink: <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkOut(Alignment,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkOut</a></code>, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkHorizontally(AlignmentHorizontal,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkHorizontally</a></code>, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkVertically(AlignmentVertical,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkVertically</a></code></p>
</li>
</ol>
<p>They can be combined using plus operator, for example:</p>
<pre class="prettyprint">
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
var visible by remember { mutableStateOf(true) }
AnimatedVisibility(
visible = visible,
enter = slideInHorizontally(
// Offsets the content by 1/3 of its width to the left, and slide towards right
initialOffsetX = { fullWidth -&gt; -fullWidth / 3 },
// Overwrites the default animation with tween for this slide animation.
animationSpec = tween(durationMillis = 200)
) + fadeIn(
// Overwrites the default animation with tween
animationSpec = tween(durationMillis = 200)
),
exit = slideOutHorizontally(
// Overwrites the ending position of the slide-out to 200 (pixels) to the right
targetOffsetX = { 200 },
animationSpec = spring(stiffness = Spring.StiffnessHigh)
) + fadeOut()
) {
// Content that needs to appear/disappear goes here:
Box(Modifier.fillMaxWidth().requiredHeight(200.dp)) {}
}</pre>
<p><b>Note</b>: <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#fadeOut(kotlin.Float,androidx.compose.animation.core.FiniteAnimationSpec)">fadeOut</a></code> and <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOut(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOut</a></code> do not affect the size of the <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code> composable. In contrast, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkOut(Alignment,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkOut</a></code> (and <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkHorizontally(AlignmentHorizontal,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkHorizontally</a></code>, <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkVertically(AlignmentVertical,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkVertically</a></code>) will shrink the clip bounds to reveal less and less of the content. This will automatically animate other layouts to fill in the space, very much like <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#(Modifier).animateContentSize(androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Function2)">animateContentSize</a></code>.</p>
<div class="devsite-table-wrapper">
<table class="responsive">
<thead>
<tr>
<th colspan="2">See also</th>
</tr>
</thead>
<tbody>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#fadeOut(kotlin.Float,androidx.compose.animation.core.FiniteAnimationSpec)">fadeOut</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOut(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOut</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOutHorizontally(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOutHorizontally</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#slideOutVertically(kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec)">slideOutVertically</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkOut(Alignment,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkOut</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkHorizontally(AlignmentHorizontal,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkHorizontally</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#shrinkVertically(AlignmentVertical,kotlin.Function1,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Boolean)">shrinkVertically</a></code></td>
<td></td>
</tr>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<h2>Summary</h2>
<div class="devsite-table-wrapper">
<table class="responsive">
<thead>
<tr>
<th colspan="2"><h3>Public companion properties</h3></th>
</tr>
</thead>
<tbody>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code></td>
<td>
<div><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.Companion.html#None()">None</a></code></div>
<p>This can be used when no built-in <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> (i.e.</p>
</td>
</tr>
</tbody>
</table>
</div>
<div class="devsite-table-wrapper">
<table class="responsive">
<thead>
<tr>
<th colspan="2"><h3>Protected companion properties</h3></th>
</tr>
</thead>
<tbody>
<tr>
<td width="40%"><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code></td>
<td>
<div><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.Companion.html#None()">None</a></code></div>
<p>This can be used when no built-in <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> (i.e.</p>
</td>
</tr>
</tbody>
</table>
</div>
<div class="devsite-table-wrapper">
<table class="responsive">
<thead>
<tr>
<th colspan="2"><h3>Public functions</h3></th>
</tr>
</thead>
<tbody>
<tr>
<td width="40%"><code>open&nbsp;operator <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a></code></td>
<td>
<div><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#equals(kotlin.Any)">equals</a>(other:&nbsp;<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html">Any</a>?)</code></div>
</td>
</tr>
<tr>
<td width="40%"><code>open <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a></code></td>
<td>
<div><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#hashCode()">hashCode</a>()</code></div>
</td>
</tr>
<tr>
<td width="40%"><code>operator <a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code></td>
<td>
<div><code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#plus(androidx.compose.animation.ExitTransition)">plus</a>(exit:&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a>)</code></div>
<p>Combines different exit transitions.</p>
</td>
</tr>
</tbody>
</table>
</div>
<h2>Public companion properties</h2>
<div><a name="getNone()"></a><a name="setNone()"></a><a name="getNone--"></a><a name="setNone--"></a>
<h3 class="api-name" id="None()">None</h3>
<pre class="api-signature no-pretty-print">val&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.Companion.html#None()">None</a>:&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></pre>
<p>This can be used when no built-in <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> (i.e. fade/slide, etc) is desired for the <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code>, but rather the children are defining their own exit animation using the <code><a href="/reference/kotlin/androidx/compose/animation/core/Transition.html">Transition</a></code> scope.</p>
<p><b>Note:</b> If <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.Companion.html#None()">None</a></code> is used, and nothing is animating in the Transition<EnterExitState> scope that <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code> provided, the content will be removed from <code><a href="/reference/kotlin/androidx/compose/animation/package-summary.html#AnimatedVisibility(kotlin.Boolean,Modifier,androidx.compose.animation.EnterTransition,androidx.compose.animation.ExitTransition,kotlin.Function1)">AnimatedVisibility</a></code> right away.</p>
<pre class="prettyprint">
import androidx.compose.animation.AnimatedVisibility
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.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.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
@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 -&gt;
// Enter transition will be animating the scale from 0.9f to 1.0f
// (i.e. PreEnter -&gt; Visible). Exit transition will be from 1.0f to
// 0.5f (i.e. Visible -&gt; PostExit)
when (enterExitState) {
EnterExitState.PreEnter -&gt; 0.9f
EnterExitState.Visible -&gt; 1.0f
EnterExitState.PostExit -&gt; 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...
}
}
@OptIn(ExperimentalAnimationApi::class, ExperimentalTransitionApi::class)
@Composable
fun AnimateMainContent(mainContentVisible: MutableTransitionState&lt;Boolean&gt;) {
Box {
// Use the `MutableTransitionState&lt;Boolean&gt;` 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 &amp;&amp; mainContentVisible.isIdle,
modifier = Modifier.align(Alignment.Center),
enter = expandVertically(),
exit = fadeOut(animationSpec = tween(50))
) {
Text(&quot;Transition Finished&quot;)
}
}
}</pre>
</div>
<h2>Public functions</h2>
<div><a name="equals-kotlin.Any-"></a><a name="equals"></a>
<h3 class="api-name" id="equals(kotlin.Any)">equals</h3>
<pre class="api-signature no-pretty-print">open&nbsp;operator&nbsp;fun&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#equals(kotlin.Any)">equals</a>(other:&nbsp;<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html">Any</a>?):&nbsp;<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a></pre>
</div>
<div><a name="hashCode--"></a><a name="hashcode"></a>
<h3 class="api-name" id="hashCode()">hashCode</h3>
<pre class="api-signature no-pretty-print">open&nbsp;fun&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#hashCode()">hashCode</a>():&nbsp;<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a></pre>
</div>
<div><a name="plus-androidx.compose.animation.ExitTransition-"></a><a name="plus"></a>
<h3 class="api-name" id="plus(androidx.compose.animation.ExitTransition)">plus</h3>
<pre class="api-signature no-pretty-print">operator&nbsp;fun&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html#plus(androidx.compose.animation.ExitTransition)">plus</a>(exit:&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a>):&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></pre>
<p>Combines different exit transitions. The order of the <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code>s being combined does not matter, as these <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code>s will start simultaneously.</p>
<pre class="prettyprint">
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
var visible by remember { mutableStateOf(true) }
AnimatedVisibility(
visible = visible,
enter = slideInVertically(
// Start the slide from 40 (pixels) above where the content is supposed to go, to
// produce a parallax effect
initialOffsetY = { -40 }
) + expandVertically(
expandFrom = Alignment.Top
) + fadeIn(initialAlpha = 0.3f),
exit = slideOutVertically() + shrinkVertically() + fadeOut()
) {
// Content that needs to appear/disappear goes here:
Text(&quot;Content to appear/disappear&quot;, Modifier.fillMaxWidth().requiredHeight(200.dp))
}</pre>
<div class="devsite-table-wrapper">
<table class="responsive">
<thead>
<tr>
<th colspan="2">Parameters</th>
</tr>
</thead>
<tbody>
<tr>
<td width="40%"><code>exit:&nbsp;<a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code></td>
<td>
<p>another <code><a href="/reference/kotlin/androidx/compose/animation/ExitTransition.html">ExitTransition</a></code> to be combined.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>