如要自訂共用元素轉換動畫的執行方式,可以使用幾個參數變更共用元素的轉換方式。
動畫規格
如要變更用於大小和位置移動的動畫規格,您可以在 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()
可防止重排。
否 |
|
---|---|
剪輯片段和疊加效果
如要讓共用元素在不同可組合項之間共用,可組合項的算繪作業會提升至圖層疊加,以便在轉換開始時與目的地中的相符項目配對。這麼做會導致該子項逸出父項的界線,以及父項的圖層轉換 (例如 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
。這麼做會導致項目變大或變小。版面配置中的所有其他項目都會回應這項變更。
|
(請注意,清單中的其他項目會因其中一個項目變大而向下移動) |
---|---|