NavDisplay предоставляет встроенные возможности анимации для создания плавных визуальных переходов при навигации пользователей в приложении. Вы можете настроить анимацию глобально для NavDisplay или на уровне Scene с помощью метаданных.
Встроенные возможности анимации
NavDisplay использует API ContentTransform, чтобы определить, как контент анимируется во время навигации. NavDisplay автоматически анимирует переходы между сценами, когда меняется ключ, полученный из класса текущей сцены и ее свойства key. Когда этот ключ меняется, NavDisplay использует ContentTransform для типа перехода (вперед, назад или с прогнозированием назад) из подходящей сцены в переходе. Если ContentTransform не определен, NavDisplay использует соответствующий переход по умолчанию.
Как переопределить переходы по умолчанию
Поведение анимации по умолчанию можно переопределить, передав параметры перехода в NavDisplay.
transitionSpec– параметр, определяющийContentTransform, которое будет применено при добавлении контента в обратный стек (то есть при переходе вперед).popTransitionSpec– параметр, который определяетContentTransform, применяемый при удалении контента из стека возврата (то есть при переходе назад).predictivePopTransitionSpec: этот параметр определяетContentTransform, которое будет применено при показе контента с помощью жеста "Назад".
Как переопределить переходы на уровне Scene
Вы можете использовать метаданные, чтобы задавать собственные анимации для отдельных сцен, используя следующие ключи метаданных, определенные NavDisplay:
NavDisplay.TransitionKey– анимация перехода вперед.NavDisplay.PopTransitionKey– анимация при переходе назад.NavDisplay.PredictivePopTransitionKey– анимация предпросмотра для жеста "Назад".
Если они указаны, то используются вместо настроек по умолчанию, заданных на уровне NavDisplay.
В приведенном ниже фрагменте кода показаны как глобальные переходы NavDisplay, так и переопределение на уровне отдельного элемента NavEntry:
@Serializable data object ScreenA : NavKey @Serializable data object ScreenB : NavKey @Serializable data object ScreenC : NavKey class AnimatedNavDisplayActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Scaffold { paddingValues -> val backStack = rememberNavBackStack(ScreenA) NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = entryProvider { entry<ScreenA> { ContentOrange("This is Screen A") { Button(onClick = { backStack.add(ScreenB) }) { Text("Go to Screen B") } } } entry<ScreenB> { ContentMauve("This is Screen B") { Button(onClick = { backStack.add(ScreenC) }) { Text("Go to Screen C") } } } entry<ScreenC>( metadata = metadata { put(NavDisplay.TransitionKey) { // Slide new content up, keeping the old content in place underneath slideInVertically( initialOffsetY = { it }, animationSpec = tween(1000) ) togetherWith ExitTransition.KeepUntilTransitionsFinished } put(NavDisplay.PopTransitionKey) { // Slide old content down, revealing the new content in place underneath EnterTransition.None togetherWith slideOutVertically( targetOffsetY = { it }, animationSpec = tween(1000) ) } put(NavDisplay.PredictivePopTransitionKey) { // Slide old content down, revealing the new content in place underneath 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 }) togetherWith slideOutHorizontally(targetOffsetX = { -it }) }, popTransitionSpec = { // Slide in from left when navigating back slideInHorizontally(initialOffsetX = { -it }) togetherWith slideOutHorizontally(targetOffsetX = { it }) }, predictivePopTransitionSpec = { // Slide in from left when navigating back slideInHorizontally(initialOffsetX = { -it }) togetherWith slideOutHorizontally(targetOffsetX = { it }) }, modifier = Modifier.padding(paddingValues) ) } } } }
Переход между сценами
В приложениях, которые создают макеты с помощью сцен, во время перехода между сценами объект NavEntry может быть включен в свойство entries обеих сцен. Внутренние механизмы NavDisplay проверяют, чтобы каждый объект отображался не более чем в одной сцене в любой момент времени. Это может приводить к резким переходам при смене сцены, в которой отрисовывается NavEntry. Чтобы обеспечить плавный переход между сценами, вы можете обернуть NavDisplay в SharedTransitionLayout и передать SharedTransitionScope в NavDisplay, как показано в следующем примере:
SharedTransitionLayout { NavDisplay( // ... sharedTransitionScope = this ) }
SharedTransitionScope в NavDisplay.SharedTransitionScope к NavDisplay.