Получите предыдущую страницу в составной навигации Jetpack на Android, чтобы управлять анимацией входа/выхода со страницы

Я хотел бы иметь разные анимации навигации для одной и той же страницы, но для разных сценариев навигации. Например.

  • страница4 -> страница1 — первая анимация.
  • страница5 -> страница1 — вторая анимация.

Практический сценарий, например. page1 — это одна из страниц из BottomNavigationBar. page5 — это страница для обновления некоторых свойств со страницы page1. Я хочу подчеркнуть, используя различные анимации навигации, что страница 1 является основной, а страница 5 — второстепенной.

Итак, я столкнулся со следующей проблемой. Я не могу найти надежное решение для получения имен «предыдущих» и «следующих» страниц. Приведенный ниже блок кода представляет собой EnterTransition для страницы 1 с оператором условия для поддержки различных анимаций на основе имени предыдущей страницы.

enterTransition = { //enterTransition for page1
                when("previousPageName") {
                    "page1" ->   fadeIn(animationSpec = tween(delayMillis = 250)) + slideInHorizontally(initialOffsetX = {-it}, animationSpec = tween(delayMillis = 150, durationMillis = 200))
                    "page2" ->  fadeIn() + slideInHorizontally()
                    else ->  fadeIn()
                }

            }

чтобы получить имя предыдущей страницы, по-видимому, лучше всего использовать NavigationController, поэтому приведенный выше пример можно переписать.

enterTransition = {  //enterTransition for page1
                when(**navController.previousBackStackEntry!!.destination.route**) {
                    "page1" ->   fadeIn(animationSpec = tween(delayMillis = 250)) + slideInHorizontally(initialOffsetX = {-it}, animationSpec = tween(delayMillis = 150, durationMillis = 200))
                    "page2" ->  fadeIn() + slideInHorizontally()
                    else ->  fadeIn()
                }

            }

Я ожидал найти там название предыдущей страницы в любое время. Но на практике, в случае, когда навигация осуществляется с помощью NavigationController.popUpBackStack(), например. нажав кнопку «вернуться назад». Он удаляет/разбивает navController.previousBackStackEntry и в результате содержит страницу, которую я не ожидаю, например. "страница3". И я могу понять такое поведение, оно работает с BackStack, но если так, то я понятия не имею, как управлять разными анимациями между разными страницами на основе состояния графа навигации. Одним из возможных решений может быть использование/управление переменной для хранения предыдущей страницы, но это последнее, что я буду использовать для достижения своих целей. Было бы неплохо найти более элегантное решение.

Итак, у меня есть пара вопросов:

  1. Существует ли какое-либо общее решение для использования разных анимаций входа/выхода для одной страницы в зависимости от сценария навигации?
  2. Как лучше всего перейти на предыдущую страницу и не беспокоиться о popUpBackStack() или
navController.navigate("page1") {
                            popUpTo(
                                "page5"
                            ) { inclusive = true }
                        }

Заранее благодарю за помощь.

Пытался получить предыдущую страницу из NavigationController.previousBackStackEntry, но без необходимого результата.

1
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как поясняется в блоге Анимации в навигационном компоновке, каждая лямбда-переход имеет формат:

enterTransition: (
    AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?
)? = null,

Что, как поясняет:

Эта лямбда использует AnimatedContentScope, чтобы предоставить вам NavBackStackEntry того, откуда вы пришли (initialState) и куда вы собираетесь (targetState). Например, для enterTransition входящим пунктом назначения является targetState — тот, к которому вы применяете enterTransition.

Это позволяет вам писать код, например:

enterTransition = {
    // initialState is the screen you are coming from (the one leaving)
    // targetState is the screen you are going to (the one entering)
    when(initialState.destination.route) {
        "page1" ->   fadeIn(animationSpec = tween(delayMillis = 250)) + slideInHorizontally(initialOffsetX = {-it}, animationSpec = tween(delayMillis = 150, durationMillis = 200))
        "page2" ->  fadeIn() + slideInHorizontally()
        else ->  fadeIn()
    }
}

Спасибо @ianhanniballake, это работает! Пропустил эту часть(

Andrei 17.08.2024 11:07

Другие вопросы по теме