애니메이션 레시피
이 레시피에서는 NavDisplay 수준과 개별 대상 수준에서 기본 애니메이션을 재정의하는 방법을 보여줍니다.
작동 방식
NavDisplay 컴포저블은 transitionSpec, popTransitionSpec, predictivePopTransitionSpec 매개변수를 사용하여 각각 앞으로 탐색, 뒤로 탐색, 뒤로 탐색 예측 애니메이션을 정의합니다. 이러한 애니메이션은 기본적으로 모든 대상에 적용됩니다.
이 예에서는 slideInHorizontally 및 slideOutHorizontally를 사용하여 앞뒤 탐색을 위한 슬라이딩 애니메이션을 만듭니다.
entry 컴포저블에 다른 transitionSpec 및 popTransitionSpec을 제공하여 특정 대상의 이러한 애니메이션을 재정의할 수도 있습니다. 이 레시피에서 ScreenC에는 맞춤 세로 슬라이드 애니메이션이 있습니다.
package com.example.nav3recipes.animations import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.animation.core.tween import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.lifecycle.compose.dropUnlessResumed import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.metadata import androidx.navigation3.runtime.rememberNavBackStack import androidx.navigation3.ui.NavDisplay import com.example.nav3recipes.content.ContentGreen import com.example.nav3recipes.content.ContentMauve import com.example.nav3recipes.content.ContentOrange import com.example.nav3recipes.ui.setEdgeToEdgeConfig import kotlinx.serialization.Serializable @Serializable private data object ScreenA : NavKey @Serializable private data object ScreenB : NavKey @Serializable private data object ScreenC : NavKey class AnimatedActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { setEdgeToEdgeConfig() super.onCreate(savedInstanceState) setContent { val backStack = rememberNavBackStack(ScreenA) NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = entryProvider { entry<ScreenA> { ContentOrange("This is Screen A") { Button(onClick = dropUnlessResumed { backStack.add(ScreenB) }) { Text("Go to Screen B") } } } entry<ScreenB> { ContentMauve("This is Screen B") { Button(onClick = dropUnlessResumed { backStack.add(ScreenC) }) { Text("Go to Screen C") } } } entry<ScreenC>( metadata = metadata { // Slide new content up, keeping the old content in place underneath put(NavDisplay.TransitionKey) { slideInVertically( initialOffsetY = { it }, animationSpec = tween(1000) ) togetherWith ExitTransition.KeepUntilTransitionsFinished } // Slide old content down, revealing the new content in place underneath put(NavDisplay.PopTransitionKey) { EnterTransition.None togetherWith slideOutVertically( targetOffsetY = { it }, animationSpec = tween(1000) ) } // Slide old content down, revealing the new content in place underneath put(NavDisplay.PredictivePopTransitionKey) { EnterTransition.None togetherWith slideOutVertically( targetOffsetY = { it }, animationSpec = tween(1000) ) } } ) { ContentGreen("This is Screen C") } }, transitionSpec = { // Slide in from right when navigating forward slideInHorizontally( initialOffsetX = { it }, animationSpec = tween(1000) ) togetherWith slideOutHorizontally( targetOffsetX = { -it }, animationSpec = tween(1000) ) }, popTransitionSpec = { // Slide in from left when navigating back slideInHorizontally( initialOffsetX = { -it }, animationSpec = tween(1000) ) togetherWith slideOutHorizontally( targetOffsetX = { it }, animationSpec = tween(1000) ) }, predictivePopTransitionSpec = { // Slide in from left when navigating back slideInHorizontally( initialOffsetX = { -it }, animationSpec = tween(1000) ) togetherWith slideOutHorizontally( targetOffsetX = { it }, animationSpec = tween(1000) ) } ) } } }