في 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);
يمكنك الاطّلاع على مثال التجارب القابلة للطي.
لترى كيف نلتقط موضع الجزء المرئي من الصفحة باستخدام
مكتبة 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()
معرّفًا يمثل القيمة كمعلمة أولى
القيمة المطلوب إدخالها كمعلمة ثانية.
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
) لإظهار أو إخفاء الطي. - استخدِم قيمة
ConstraintSet
منفصلة لكل حالة من الحالات القابلة للطي كما تريد. الدعم (closed
أوfolded
أوfully open
).
جارٍ إضافة تأثيرات متحركة لـ ConstraintSet
تمت إضافة الدالة updateStateAnimate()
في MotionLayout
في 2.1
الإصدار:
Kotlin
fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)
Java
void updateStateAnimate(int stateId, ConstraintSet set, int duration);
ستعمل هذه الدالة على تحريك التغييرات تلقائيًا عند تحديث قيمة
ConstraintSet
بدلاً من إجراء تحديث فوري (ويمكنك تنفيذ ذلك باستخدام
updateState(stateId, constraintset)
). يتيح لك ذلك تحديث واجهة المستخدم
معدّل الذباب وفقًا للتغييرات، مثل الحالة القابلة للطيّ التي لديك
ReactiveGuide
داخل MotionLayout
تتيح الدالة ReactiveGuide
أيضًا استخدام سمتَين مفيدتَين عند استخدامها داخل
MotionLayout
:
app:reactiveGuide_animateChange="true|false"
app:reactiveGuide_applyToAllConstraintSets="true|false"
سيُجري العنصر الأول تعديلاً على ConstraintSet
الحالي ويحرّك التغيير
تلقائيًا. وسيطبّق الخيار الثاني القيمة الجديدة ReactiveGuide
.
إلى كل ConstraintSet
في MotionLayout
. نهج نموذجي
بالنسبة إلى الهواتف القابلة للطيّ، عليك استخدام رمز ReactiveGuide
الذي يمثّل موضع الطي
إعداد عناصر التنسيق نسبةً إلى ReactiveGuide
.
استخدام عدة ConstraintSet
لعرض حالة قابلة للطي
بدلاً من تعديل حالة MotionLayout
الحالية، يمكنك استخدام طريقة أخرى للهندسة
بالنسبة إلى واجهة المستخدم التي تتيح استخدام الهواتف القابلة للطيّ، عليكم إنشاء حالات منفصلة محدّدة (بما في ذلك
closed
وfolded
وfully open
).
في هذا السيناريو، قد تكون لا تزال تريد استخدام ReactiveGuide
لتمثيل
في الجزء المرئي من الصفحة، ولكن سيكون لديك قدر أكبر من التحكم (مقارنةً بميزة التشغيل التلقائي
رسم متحرك عند تحديث ConstraintSet
الحالية) حول كيفية عمل كل حالة
الانتقال إلى مرحلة أخرى.
ومن خلال هذه الطريقة، يمكنك ببساطة في مستمع DeviceState
توجيه
MotionLayout
للانتقال إلى حالات محددة من خلال
MotionLayout.transitionToState(stateId)
.