Dalam rilis ConstraintLayout
2.1, beberapa fitur ditambahkan untuk membantu
mengelola perangkat foldable, termasuk SharedValues
,
ReactiveGuide
, dan peningkatan dukungan untuk animasi dengan MotionLayout
.
Nilai yang Dibagikan
Kami menambahkan mekanisme baru untuk memasukkan nilai runtime di ConstraintLayout
– ini dimaksudkan untuk digunakan untuk nilai seluruh sistem, karena semua instance ConstraintLayout
dapat mengakses nilai.
Dalam konteks perangkat foldable, kita dapat menggunakan mekanisme ini untuk memasukkan posisi lipatan saat runtime:
Kotlin
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)
Java
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);
Dalam helper kustom, Anda dapat mengakses nilai bersama dengan menambahkan pemroses untuk setiap perubahan:
Kotlin
val sharedValues: SharedValues = ConstraintLayout.getSharedValues() sharedValues.addListener(mAttributeId, this)
Java
SharedValues sharedValues = ConstraintLayout.getSharedValues(); sharedValues.addListener(mAttributeId, this);
Anda dapat melihat contoh FoldableExperiments
untuk melihat cara kami merekam posisi lipatan menggunakan
library Jetpack WindowManager dan memasukkan
posisi ke 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()
mengambil ID yang mewakili nilai sebagai parameter pertama dan
nilai yang akan dimasukkan sebagai parameter kedua.
ReactiveGuide
Salah satu cara untuk memanfaatkan SharedValue
di tata letak, tanpa harus
menulis kode, adalah dengan menggunakan helper
ReactiveGuide
. Tindakan ini akan memosisikan panduan horizontal atau vertikal sesuai dengan
SharedValue
tertaut.
<androidx.constraintlayout.widget.ReactiveGuide
android:id="@+id/fold"
app:reactiveGuide_valueId="@id/fold"
android:orientation="horizontal" />
Selanjutnya, data ini dapat digunakan seperti yang Anda lakukan dengan panduan normal.
MotionLayout
untuk perangkat foldable
Kami menambahkan beberapa fitur dalam MotionLayout
pada versi 2.1 yang membantu
memetakan status – sesuatu yang sangat berguna untuk perangkat foldable, karena biasanya
kami harus menangani animasi di antara berbagai tata letak yang mungkin.
Ada dua pendekatan yang tersedia untuk perangkat foldable:
- Saat runtime, perbarui tata letak saat ini (
ConstraintSet
) untuk menampilkan atau menyembunyikan lipatan. - Gunakan
ConstraintSet
terpisah untuk setiap status perangkat foldable yang ingin Anda dukung (closed
,folded
, ataufully open
).
Menganimasikan ConstraintSet
Fungsi updateStateAnimate()
di MotionLayout
telah ditambahkan dalam rilis 2.1:
Kotlin
fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)
Java
void updateStateAnimate(int stateId, ConstraintSet set, int duration);
Fungsi ini akan otomatis menganimasikan perubahan saat mengupdate ConstraintSet
tertentu, bukan melakukan update langsung (yang dapat Anda lakukan dengan
updateState(stateId, constraintset)
). Hal ini memungkinkan Anda mengupdate UI
dengan cepat, bergantung pada perubahan, seperti status perangkat foldable mana yang Anda gunakan.
ReactiveGuide
di dalam MotionLayout
ReactiveGuide
juga mendukung dua atribut yang berguna saat digunakan di dalam
MotionLayout
:
app:reactiveGuide_animateChange="true|false"
app:reactiveGuide_applyToAllConstraintSets="true|false"
Fungsi pertama akan mengubah ConstraintSet
saat ini dan menganimasikan perubahan
secara otomatis. Yang kedua akan menerapkan nilai baru dari posisi ReactiveGuide
ke semua ConstraintSet
di MotionLayout
. Pendekatan standar untuk
perangkat foldable adalah menggunakan ReactiveGuide
yang mewakili posisi lipatan,
dengan menyiapkan elemen tata letak relatif terhadap ReactiveGuide
.
Menggunakan beberapa ConstraintSet
untuk menampilkan status perangkat foldable
Daripada memperbarui status MotionLayout
saat ini, cara lain untuk merancang
UI Anda guna mendukung perangkat foldable adalah dengan membuat status terpisah tertentu (termasuk
closed
, folded
, dan fully open
).
Dalam skenario ini, Anda mungkin masih ingin menggunakan ReactiveGuide
untuk mewakili
lipatan, tetapi Anda akan memiliki lebih banyak kontrol (dibandingkan dengan animasi
otomatis saat memperbarui ConstraintSet
saat ini) terkait cara setiap status akan
beralih ke status lain.
Dengan pendekatan ini, di pemroses DeviceState
, Anda cukup mengarahkan
MotionLayout
untuk bertransisi ke status tertentu melalui
metode
MotionLayout.transitionToState(stateId)
.