ConstraintLayout
2.1 リリースでは、折りたたみ式デバイスの管理に役立つ機能(SharedValues
、ReactiveGuide
など)が追加され、MotionLayout
でのアニメーションのサポートも強化されました。
共有される値
ConstraintLayout
にランタイム値を挿入する新しいメカニズムを追加しました。これは、ConstraintLayout
のすべてのインスタンスが値にアクセスできるため、システム全体の値に使用することを目的としています。
折りたたみ式デバイスのコンテキストでは、次のメカニズムを使用して、実行時に折りたたみの位置を挿入できます。
Kotlin
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)
Java
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);
カスタム ヘルパーでは、変更に対するリスナーを追加することで、共有値にアクセスできます。
Kotlin
val sharedValues: SharedValues = ConstraintLayout.getSharedValues() sharedValues.addListener(mAttributeId, this)
Java
SharedValues sharedValues = ConstraintLayout.getSharedValues(); sharedValues.addListener(mAttributeId, this);
FoldableExperiments の例では、Jetpack WindowManager ライブラリを使用して折りたたみの位置をキャプチャし、その位置を ConstraintLayout
に挿入する方法を確認できます。
Kotlin
inner class StateContainer : Consumer<WindowLayoutInfo> { override fun accept(newLayoutInfo: WindowLayoutInfo) { // Add views that represent display features for (displayFeature in newLayoutInfo.displayFeatures) { val foldFeature = displayFeature as? FoldingFeature if (foldFeature != null) { if (foldFeature.isSeparating && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL ) { // The foldable device is in tabletop mode val fold = foldPosition(motionLayout, foldFeature) ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold) } else { ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0); } } } } }
Java
class StateContainer implements Consumer<WindowLayoutInfo> { @Override public void accept(WindowLayoutInfo newLayoutInfo) { // Add views that represent display features for (DisplayFeature displayFeature : newLayoutInfo.getDisplayFeatures()) { if (displayFeature instanceof FoldingFeature) { FoldingFeature foldFeature = (FoldingFeature)displayFeature; if (foldFeature.isSeparating() && foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL ) { // The foldable device is in tabletop mode int fold = foldPosition(motionLayout, foldFeature); ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold); } else { ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0); } } } } }
fireNewValue()
は、最初のパラメータとして値を表す ID と、2 番目のパラメータとして挿入する値を表す ID を受け取ります。
ReactiveGuide
コードを記述することなくレイアウトで SharedValue
を利用する方法の 1 つは、ReactiveGuide
ヘルパーを使用することです。これにより、リンクされた SharedValue
に従って、水平または垂直のガイドラインが配置されます。
<androidx.constraintlayout.widget.ReactiveGuide
android:id="@+id/fold"
app:reactiveGuide_valueId="@id/fold"
android:orientation="horizontal" />
そうすれば、通常のガイドラインと同じように使用できます。
MotionLayout
(折りたたみ式デバイスの場合)
2.1 の MotionLayout
には、状態のモーフィングに役立ついくつかの機能を追加しました。これは、折りたたみ式デバイスでは通常、可能なレイアウト間でのアニメーション化を処理する必要があるため、特に有用な機能です。
折りたたみ式デバイスには、次の 2 つの方法があります。
- 実行時に、現在のレイアウト(
ConstraintSet
)を更新して、折りたたみの表示と非表示を切り替えます。 - サポートする折りたたみ式の状態(
closed
、folded
、fully open
)ごとに、個別のConstraintSet
を使用します。
ConstraintSet
をアニメーション化する
MotionLayout
の関数 updateStateAnimate()
は 2.1 リリースで追加されました。
Kotlin
fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)
Java
void updateStateAnimate(int stateId, ConstraintSet set, int duration);
この関数は、即時更新(updateState(stateId, constraintset)
で可能)ではなく、特定の ConstraintSet
の更新時に変更を自動的にアニメーション化します。これにより、折りたたみ式デバイスの現在の状態などの変更に応じて、その場で UI を更新できます。
MotionLayout
内の ReactiveGuide
ReactiveGuide
は、MotionLayout
内で使用する場合に、次の 2 つの有用な属性もサポートします。
app:reactiveGuide_animateChange="true|false"
app:reactiveGuide_applyToAllConstraintSets="true|false"
最初のメソッドは、現在の ConstraintSet
を変更し、その変更を自動的にアニメーション化します。2 つ目は、ReactiveGuide
位置の新しい値を MotionLayout
内のすべての ConstraintSet
に適用します。折りたたみ式デバイスでの一般的なアプローチは、折りたたみ位置を表す ReactiveGuide
を使用して、ReactiveGuide
を基準としてレイアウト要素を設定することです。
複数の ConstraintSet
を使用して折りたたみ式の状態を表す
折りたたみ式デバイスをサポートするように UI を設計するもう 1 つの方法は、現在の MotionLayout
の状態を更新する代わりに、特定の個別の状態(closed
、folded
、fully open
など)を作成することです。
このシナリオでは、引き続き ReactiveGuide
を使用して折りたたみを表現することもできますが、各状態がどのように別の状態に移行するかについて、より細かく制御できます(現在の ConstraintSet
を更新するときの自動アニメーションと比較した場合)。
この方法では、DeviceState
リスナーの MotionLayout.transitionToState(stateId)
メソッドで、MotionLayout
が特定の状態に遷移するように単純に指示できます。