ফোল্ডেবল ডিভাইসের জন্য ডিজাইন করা

ConstraintLayout ২.১ রিলিজে, ফোল্ডেবল ডিভাইস ম্যানেজ করতে সাহায্য করার জন্য বেশ কিছু ফিচার যোগ করা হয়েছে, যার মধ্যে রয়েছে SharedValues, ReactiveGuide এবং MotionLayout-এর সাথে অ্যানিমেশনের জন্য উন্নত সহায়তা।

শেয়ার করা ভ্যালু

আমরা ConstraintLayout-এ রানটাইম ভ্যালু ইনজেক্ট করার জন্য একটি নতুন মেকানিজম যোগ করেছি – এটি সিস্টেম-ওয়াইড ভ্যালুর জন্য ব্যবহার করার উদ্দেশ্যে তৈরি করা হয়েছে, কারণ ConstraintLayout-এর সব ইনস্ট্যান্স ভ্যালু অ্যাক্সেস করতে পারে।

ফোল্ডেবল ডিভাইসের ক্ষেত্রে, রানটাইমে ফোল্ডের পজিশন ইনজেক্ট করতে আমরা এই মেকানিজম ব্যবহার করতে পারি:

Kotlin

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

জাভা

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

কাস্টম হেল্পারে, আপনি যেকোনও পরিবর্তনের জন্য লিসেনার যোগ করে শেয়ার করা ভ্যালু অ্যাক্সেস করতে পারবেন:

Kotlin

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

জাভা

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

Jetpack WindowManager লাইব্রেরি ব্যবহার করে আমরা কীভাবে ফোল্ডের পজিশন ক্যাপচার করি এবং ConstraintLayout-এ পজিশন ইনজেক্ট করি তা দেখতে FoldableExperiments উদাহরণ দেখতে পারেন।

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

জাভা

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 অ্যানিমেট করা হচ্ছে

MotionLayout-এ updateStateAnimate() ফাংশনটি 2.1 রিলিজে যোগ করা হয়েছে:

Kotlin

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

জাভা

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

এই ফাংশনটি অবিলম্বে আপডেট করার পরিবর্তে (যা আপনি updateState(stateId, constraintset)-এর মাধ্যমে করতে পারেন) প্রদত্ত ConstraintSet আপডেট করার সময় পরিবর্তনগুলি অটোমেটিক অ্যানিমেট করবে। এটি আপনাকে পরিবর্তনগুলির উপর নির্ভর করে, যেমন আপনি কোন ফোল্ডেবল অবস্থায় আছেন, তার উপর ভিত্তি করে আপনার UI আপডেট করতে দেয়।

MotionLayout-এর মধ্যে ReactiveGuide

ReactiveGuide-এর মধ্যে ব্যবহার করা হলে, MotionLayout-এ দুটি উপযোগী অ্যাট্রিবিউটও কাজ করে:

  • app:reactiveGuide_animateChange="true|false"

  • app:reactiveGuide_applyToAllConstraintSets="true|false"

প্রথমটি বর্তমান ConstraintSet পরিবর্তন করবে এবং পরিবর্তনটি অটোমেটিক অ্যানিমেট করবে। দ্বিতীয়টি ReactiveGuide পজিশনের নতুন ভ্যালু MotionLayout-এর সব ConstraintSet-এ প্রয়োগ করবে। ফোল্ডেবল ডিভাইসের ক্ষেত্রে সাধারণত ReactiveGuide ব্যবহার করে ফোল্ড পজিশন দেখানো হয়, ReactiveGuide-এর সাপেক্ষে আপনার লেআউট এলিমেন্ট সেট-আপ করা হয়।

ভাঁজ করা যায় এমন অবস্থা দেখানোর জন্য একাধিক ConstraintSet ব্যবহার করা হচ্ছে

বর্তমান MotionLayout স্টেট আপডেট করার পরিবর্তে, ফোল্ডেবল ডিভাইসের জন্য আপনার UI আর্কিটেক্ট করার আরেকটি উপায় হল নির্দিষ্ট আলাদা স্টেট তৈরি করা (closed, folded এবং fully open সহ)।

এই পরিস্থিতিতে, আপনি এখনও ফোল্ড দেখানোর জন্য ReactiveGuide ব্যবহার করতে চাইতে পারেন, তবে প্রতিটি স্টেট কীভাবে অন্য স্টেটে ট্রানজিশন করবে তার উপর আপনার অনেক বেশি নিয়ন্ত্রণ থাকবে (বর্তমান ConstraintSet আপডেট করার সময় অটোমেটিক অ্যানিমেশনের তুলনায়)।

এই পদ্ধতিতে, আপনার DeviceState লিসেনারে, আপনি শুধু MotionLayout-কে MotionLayout.transitionToState(stateId) পদ্ধতির মাধ্যমে নির্দিষ্ট স্টেটে ট্রানজিশন করতে নির্দেশ দেবেন।