Hedefler arasında animasyonlu geçiş

NavDisplay, kullanıcılar uygulamanızda gezinirken sorunsuz görsel geçişler oluşturmak için yerleşik animasyon özellikleri sunar. Bu animasyonları NavDisplay için genel olarak veya meta verileri kullanarak Scene düzeyinde özelleştirebilirsiniz.

Yerleşik animasyon özelliklerini anlama

NavDisplay, gezinme sırasında içeriğin nasıl animasyonlu hale getirileceğini tanımlamak için ContentTransform API'yi kullanır. NavDisplay, geçerli sahnenin sınıfından türetilen bir anahtar ve key özelliği değiştiğinde sahneler arasındaki geçişleri otomatik olarak canlandırır. Bu anahtar değiştiğinde NavDisplay, geçişteki uygun sahneden geçiş türü (ileri, geri veya tahmin edilen geri gitme) için ContentTransform kullanır. Bu ContentTransform tanımlanmamışsa NavDisplay, ilgili varsayılan geçişi kullanır.

Varsayılan geçişleri geçersiz kılma

NavDisplay için geçiş parametreleri sağlayarak varsayılan animasyon davranışlarını geçersiz kılabilirsiniz.

  • transitionSpec: Bu parametre, içerik eski yığına eklendiğinde (ör. ileri doğru gezinirken) uygulanacak ContentTransform değerini tanımlar.
  • popTransitionSpec: Bu parametre, içerik eski yığından kaldırıldığında (ör. geri gidildiğinde) uygulanacak ContentTransform değerini tanımlar.
  • predictivePopTransitionSpec: Bu parametre, tahmin edilen geri gitme hareketi kullanılarak içerik açıldığında uygulanacak ContentTransform değerini tanımlar.

Scene düzeyinde geçişleri geçersiz kılma

NavDisplay tarafından tanımlanan aşağıdaki meta veri anahtarlarını kullanarak her bir sahne için özel animasyonlar tanımlamak üzere meta verileri kullanabilirsiniz:

Sağlandığında, bu sahne düzeyindeki geçişler NavDisplay üzerinde ayarlanan ilgili varsayılanlar yerine kullanılır.

Aşağıdaki snippet'te hem genel NavDisplay geçişleri hem de bağımsız NavEntry düzeyinde bir geçersiz kılma gösterilmektedir:

@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)
                )
            }
        }
    }
}

Şekil 1. Özel animasyonlar içeren uygulama.

Sahneler arasında gezinme girişlerini geçirme

Sahneleri kullanarak özel düzenler oluşturan uygulamalarda, geçiş sırasında her iki sahnenin entries özelliğine bir NavEntry dahil edilebilir. Dahili olarak NavDisplay, her girişin herhangi bir zamanda en fazla bir sahnede gösterildiğini doğrular. Bu durum, NavEntry öğesini oluşturan sahne değiştiğinde geçişlerin kesintili olmasına neden olabilir. Sahneler arasındaki girişleri sorunsuz bir şekilde canlandırmak için NavDisplay öğenizi SharedTransitionLayout içine sarmalayabilir ve aşağıdaki örnekte gösterildiği gibi NavDisplay öğesine SharedTransitionScope sağlayabilirsiniz:

SharedTransitionLayout {
    NavDisplay(
        // ...
        sharedTransitionScope = this
    )
}

Şekil 2. SharedTransitionScope, NavDisplay öğesine iletilmediğinde geçişte kesinti yaşanıyor.
Şekil 3. SharedTransitionScope, NavDisplay'e geçerken sorunsuz geçiş.