طراحی برای وسایل تاشو

در نسخه ConstraintLayout 2.1، چندین ویژگی برای کمک به مدیریت دستگاه های تاشو اضافه شد، از جمله SharedValues ، ReactiveGuide ، و پشتیبانی پیشرفته از انیمیشن با MotionLayout .

ارزش های مشترک

ما یک مکانیسم جدید برای تزریق مقادیر زمان اجرا در ConstraintLayout اضافه کردیم - این در نظر گرفته شده است که برای مقادیر در سراسر سیستم استفاده شود، زیرا تمام نمونه های ConstraintLayout قادر به دسترسی به مقدار هستند.

در زمینه دستگاه های تاشو، می توانیم از این مکانیسم برای تزریق موقعیت تا در زمان اجرا استفاده کنیم:

کاتلین

ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)

جاوا

ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);

در یک Helper سفارشی، می‌توانید با افزودن یک شنونده برای هر گونه تغییر، به مقادیر مشترک دسترسی داشته باشید:

کاتلین

val sharedValues: SharedValues = ConstraintLayout.getSharedValues()
sharedValues.addListener(mAttributeId, this)

جاوا

SharedValues sharedValues = ConstraintLayout.getSharedValues();
sharedValues.addListener(mAttributeId, this);

می‌توانید به مثال FoldableExperiments نگاه کنید تا ببینید که چگونه با استفاده از کتابخانه Jetpack WindowManager موقعیت فولد را ضبط کرده و موقعیت را به ConstraintLayout تزریق می‌کنیم.

کاتلین

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

جاوا

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 اضافه شد:

کاتلین

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

جاوا

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

این تابع به‌جای انجام به‌روزرسانی فوری (که می‌توانید با updateState(stateId, constraintset) انجام دهید، هنگام به‌روزرسانی یک 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) هدایت می کنید.