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