NavDisplay 提供內建動畫功能,可在使用者瀏覽應用程式時,建立流暢的視覺轉場效果。您可以使用中繼資料,在 NavDisplay 或 Scene 層級全域自訂這些動畫。
瞭解內建動畫功能
NavDisplay 使用 ContentTransform API 定義內容在導覽期間的動畫效果。當衍生自目前場景類別的索引鍵及其 key 屬性變更時,NavDisplay 會自動為場景之間的轉場效果加上動畫。當這個索引鍵變更時,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 時,可流暢切換。