針對折疊式裝置設計

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 支援 (closedfoldedfully 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

ReactiveGuideMotionLayout

  • app:reactiveGuide_animateChange="true|false"

  • app:reactiveGuide_applyToAllConstraintSets="true|false"

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

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

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

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

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