在 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 做為第一個參數,並將要插入的值做為第二個參數。
ReactiveGuide
不必編寫任何程式碼即可在版面配置中使用 SharedValue
的方法之一,就是使用 ReactiveGuide
輔助程式。這會根據連結的 SharedValue
放置水平或垂直引導線。
<androidx.constraintlayout.widget.ReactiveGuide
android:id="@+id/fold"
app:reactiveGuide_valueId="@id/fold"
android:orientation="horizontal" />
以便與一般指南搭配使用。
MotionLayout
適用於折疊式裝置
我們在 MotionLayout
2.1 版中新增了多項功能,協助調整變形狀態,特別適合折疊式裝置使用,因為我們通常必須處理不同可能版面配置之間的動畫。
折疊式裝置可使用以下兩種方式:
- 在執行階段更新目前的版面配置 (
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);
此函式會在更新特定 ConstraintSet
時自動以動畫方式呈現變更,而無需立即更新 (您可以使用 updateState(stateId, constraintset)
執行)。這可讓您根據變更 (例如目前所在的折疊式狀態) 即時更新 UI。
MotionLayout
中的 ReactiveGuide
ReactiveGuide
也支援在 MotionLayout
中使用時有兩個實用的屬性:
app:reactiveGuide_animateChange="true|false"
app:reactiveGuide_applyToAllConstraintSets="true|false"
第一個選項會修改目前的 ConstraintSet
,並自動為變更加上動畫效果。第二個值會將 ReactiveGuide
位置的新值套用至 MotionLayout
中的所有 ConstraintSet
。折疊式裝置的常見做法是使用代表折疊位置的 ReactiveGuide
,設定相對於 ReactiveGuide
的版面配置元素。
使用多個 ConstraintSet
代表折疊式裝置狀態
如要架構支援折疊式裝置的 UI,與其更新目前的 MotionLayout
狀態,另一種做法是建立特定的獨立狀態 (包括 closed
、folded
和 fully open
)。
在這種情況下,您可能仍希望使用 ReactiveGuide
代表折疊位置,但相較於更新目前的 ConstraintSet
時的自動化動畫,您可以進一步掌控各狀態如何轉換為其他狀態。
使用這種方法時,在 DeviceState
事件監聽器中,您只須透過 MotionLayout.transitionToState(stateId)
方法,將 MotionLayout
導向特定狀態。