針對折疊式裝置設計

在 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);

查看 FoldableExperimentals 範例 看看如何運用 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 做為第一個參數, 要插入為第二個參數的值

ReactiveGuide

在版面配置中利用 SharedValue 的其中一種方式,而不必 就是使用 ReactiveGuide 輔助程式。即可根據 已連結「SharedValue」。

    <androidx.constraintlayout.widget.ReactiveGuide
        android:id="@+id/fold"
        app:reactiveGuide_valueId="@id/fold"
        android:orientation="horizontal" />

這樣就能像一般指南一樣運用它。

MotionLayout 適用於摺疊式裝置

我們在 2.1 的 MotionLayout 中新增了幾項有助於變形的功能 這對摺疊式裝置特別有用,因為我們通常 必須處理各種可能的版面配置之間動畫效果

折疊式裝置有兩種方法:

  • 在執行階段,更新目前的版面配置 (ConstraintSet),即可顯示或隱藏 摺疊位置。
  • 對於每個需要的摺疊式裝置狀態,請使用個別的 ConstraintSet 支援 (closed、folded 或 fully open)。

為 ConstraintSet 建立動畫效果

MotionLayout 中的 updateStateAnimate() 函式已於 2.1 版中新增 版本:

Kotlin

fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)

Java

void updateStateAnimate(int stateId, ConstraintSet set, int duration);

這個函式會在更新指定的 ConstraintSet,這樣就不必執行立即更新 (也可透過 updateState(stateId, constraintset))。這樣一來,您就能更新 套用變更,例如當下的摺疊式裝置狀態。

MotionLayout 中的 ReactiveGuide

ReactiveGuide在 MotionLayout:

  • app:reactiveGuide_animateChange="true|false"

  • app:reactiveGuide_applyToAllConstraintSets="true|false"

第一個指令會修改目前的 ConstraintSet 並加上動畫效果 。第二個做法是套用 ReactiveGuide 的新值 移至 MotionLayout 中的所有 ConstraintSet。一般來說 摺疊式裝置建議您使用 ReactiveGuide 代表摺疊位置 設定相對於 ReactiveGuide 的版面配置元素。

使用多個 ConstraintSet 表示摺疊式裝置狀態

無須更新目前的 MotionLayout 狀態,改採其他架構的方式 建立特定獨立狀態 (包括 closed、folded 和 fully open)。

在這種情況下,建議您還是使用 ReactiveGuide 來代表 但相較於自動化功能 更新目前 ConstraintSet 時的動畫),其中說明各狀態會如何 轉換至其他容器

使用這個方法時,只要在 DeviceState 事件監聽器中將 使用 MotionLayout 轉換為特定狀態 MotionLayout.transitionToState(stateId)敬上 方法。