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'sini kullanır. Mevcut sahnenin sınıfından türetilen bir anahtar ve bu anahtarın key özelliği değiştiğinde NavDisplay, sahneler arasındaki geçişleri otomatik olarak animasyonlandırır. Bu anahtar değiştiğinde, NavDisplay, geçiş türü (ileri, geri veya tahmini geri) için ContentTransform kullanır. Bu ContentTransform tanımlanmamışsa NavDisplay, karşılık gelen varsayılan geçişi kullanır.

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

NavDisplay öğesine 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 (yani ileriye doğru gidilirken) uygulanacak ContentTransform tanımlar.
  • popTransitionSpec: Bu parametre, içerik eski yığından kaldırıldığında (ör. geri gidildiğinde) uygulanacak ContentTransform öğesini tanımlar.
  • predictivePopTransitionSpec: Bu parametre, içerik, tahmini geri hareket kullanılarak açıldığında uygulanacak ContentTransform değerini tanımlar.

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

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

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

Aşağıdaki snippet hem genel NavDisplay geçişleri hem de tek tek NavEntry düzeyinde geçersiz kılmayı gösterir:

@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şleri arasında geçiş yapma

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şturulan sahne değiştiğinde geçişlerin titrek olmasına neden olabilir. Girişleri sahneler arasında sorunsuz bir şekilde canlandırmak için NavDisplay öğenizi SharedTransitionLayout içine yerleştirebilir ve aşağıdaki örnekte gösterildiği gibi SharedTransitionScope öğesini NavDisplay öğesine sağlayabilirsiniz:

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