共有要素遷移アニメーションの実行方法をカスタマイズするには、いくつかの方法があります。 共有要素の遷移方法を変更するために使用できるパラメータです。
アニメーション仕様
サイズと位置の移動に使用されるアニメーション仕様を変更するには、
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
パラメータを示す例サイズ変更モード
2 つの共有境界間でアニメーション化する場合は、resizeMode
パラメータを設定できます。
RemeasureToBounds
または ScaleToBounds
のいずれか。このパラメータは、共有要素が 2 つの状態間でどのように遷移するかを決定します。ScaleToBounds
は、まず先読み(またはターゲット)制約を使用して子レイアウトを測定します。次に、
子の安定版レイアウトは、共有境界内に収まるようにスケーリングされます。
ScaleToBounds
は「グラフィカル スケール」と考えることができます。マッピングします。
一方、RemeasureToBounds
は、ターゲット サイズに基づいてアニメーション化された固定制約を使用して、sharedBounds
の子レイアウトを再測定して再レイアウトします。「
再測定は境界サイズ変更によってトリガーされるため、
あります。
Text
コンポーザブルの場合は、テキストの再レイアウトと別の行への再フローを回避できるため、ScaleToBounds
を使用することをおすすめします。異なるアスペクトの境界の場合
要素間で滑らかな連続性が求められる場合は、
RemeasureToBounds
をおすすめします。
2 つのサイズ変更モードの違いを以下の例に示します。
|
|
---|---|
最終レイアウトにスキップ
デフォルトでは、2 つのレイアウトを切り替えるとき、レイアウトのサイズは開始状態から最終状態までアニメーション化されます。これは、テキストなどのコンテンツをアニメーション化する場合に望ましくない動作になる可能性があります。
次の例は、説明文「Lorem Ipsum」が 2 つの異なる方法で画面に表示される様子を示しています。最初の例ではテキストが
コンテナのサイズが大きくなると入力されるようになります。2 つ目の例では、
リフローします。Modifier.skipToLookaheadSize()
を追加するとリフローを防ぐ
成長していきます。
Modifier.skipToLookahead() なし - 「Lorem Ipsum」に注目テキストのリフロー |
Modifier.skipToLookahead() - 「Lorem Ipsum」というテキストは、アニメーションの開始時に最終状態を維持します。 |
---|---|
クリップとオーバーレイ
Compose で共有要素を作成する際の重要なコンセプトは、異なるコンポーザブル間で共有するために、遷移が開始されて宛先で一致すると、コンポーザブルのレンダリングがレイヤ オーバーレイにエレベートされることです。その結果、この関数が 親の境界とそのレイヤ変換(アルファやスケールなど)。
他の共有されていない 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
に変更します。これにより、アイテムが拡大または縮小されます。レイアウト内の他のすべてのアイテムは
適用できます。
|
(1 つのアイテムが拡大すると、リスト内の他のアイテムが下に移動します)。 |
---|---|