如要自訂共用元素轉換動畫的執行方式,可以使用幾個參數變更共用元素轉換方式。
動畫規格
如要變更用於大小和位置動作的動畫規格,可以在 Modifier.sharedElement()
指定不同的 boundsTransform
參數。這會提供初始的 Rect
位置和目標 Rect
位置。
舉例來說,如要讓上述範例的文字使用弧形動作來移動,請指定 boundsTransform
參數以使用 keyframes
規格:
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
您可以使用任何 AnimationSpec
。這個範例使用 keyframes
規格。
boundsTransform
參數的範例調整大小模式
在兩個共用邊界之間建立動畫效果時,您可以將 resizeMode
參數設為 RemeasureToBounds
或 ScaleToBounds
。這個參數可決定共用元素在兩個狀態之間轉換的方式。ScaleToBounds
會先使用前看 (或目標) 限制測量子版面配置。接著,子項的穩定版面配置會縮放,以符合共用邊界。ScaleToBounds
可以視為狀態之間的「圖形比例」。
而 RemeasureToBounds
會根據目標大小,重新測量 sharedBounds
的子版面配置並重新安排版面配置,並套用動畫固定限制。重新測量作業會由邊界大小變更觸發,而範圍可能可能是每個影格。
針對 Text
可組合項,建議您使用 ScaleToBounds
,以免他人將文字重新版面配置以及將文字重排在不同行。對於不同顯示比例的邊界,如果您想讓兩個共用元素之間保持流動連續性,建議使用 RemeasureToBounds
。
兩種大小調整模式之間的差異如以下範例所示:
|
|
---|---|
跳至最終版面配置
根據預設,在兩個版面配置之間轉換時,版面配置大小會在開始和最終狀態之間建立動畫。在為文字等動畫內容呈現動畫時,這個行為可能是不理想的行為。
以下範例說明「Lorem Ipsum」說明文字以兩種方式進入畫面。第一個範例會在容器大小變大時,文字自動重排,第二個範例則不會隨著容器成長而自動重排。新增 Modifier.skipToLookaheadSize()
可防止在成長時重流。
沒有 Modifier.skipToLookahead() - 請留意「Lorem Ipsum」文字重排 |
Modifier.skipToLookahead() - 請注意,「Lorem Ipsum」文字會在動畫開始時維持最終狀態 |
---|---|
剪輯和重疊
在 Compose 中建立共用元素時,其中一個重要概念,是為了讓這些元素在不同可組合項之間共用,而當轉換開始到目的地相符時,可組合項的算繪會向上提升為圖層疊加。這樣做的效果是會逸出父項邊界及其圖層轉換 (例如 Alpha 和縮放)。
它會在其他非共用的 UI 元素上方顯示,轉換完成後,該元素就會從重疊移至其專屬的 DrawScope
。
如要將共用元素裁剪成形狀,請使用標準 Modifier.clip()
函式。將其放在 sharedElement()
後方:
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
如要確保共用元素一律不會在父項容器外轉譯,您可以在 sharedElement()
上設定 clipInOverlayDuringTransition
。根據預設,針對巢狀共用邊界,clipInOverlayDuringTransition
會使用父項 sharedBounds()
的裁剪路徑。
如要支援將特定 UI 元素 (例如底部列或懸浮動作按鈕) 保留在共用元素轉換的上方,請使用 Modifier.renderInSharedTransitionScopeOverlay()
。根據預設,這個修飾符會在共用轉換啟用期間,將內容保留在疊加畫面中。
舉例來說,在 Jetsnack 中,BottomAppBar
需要置於共用元素上方,直到螢幕無法顯示為止。對可組合項新增修飾符,可保持進階。
沒有 |
登入 |
---|---|
有時候,您可能希望非共用的可組合項在轉換之前建立動畫,並留在其他可組合項上方。在這些情況下,請在執行共用元素轉換時,使用 renderInSharedTransitionScopeOverlay().animateEnterExit()
為可組合項建立動畫:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
在極少數情況下,不希望共用元素在疊加層中算繪,您可以將 sharedElement()
上的 renderInOverlayDuringTransition
設為 false。
向同層級版面配置通知共用元素大小變更
根據預設,sharedBounds()
和 sharedElement()
不會在版面配置轉換時,通知任何大小的父項容器。
如要在父項容器轉換期間套用大小變更,請將 placeHolderSize
參數變更為 PlaceHolderSize.animatedSize
。否則項目會變大或縮小。版面配置中的所有其他項目都會回應變更。
|
(請留意清單中其他項目如何因應持續增長的項目) |
---|---|