আপনার অ্যাপ্লিকেশন ভাঁজ সচেতন করুন

বড় আকারের আনফোল্ডেড ডিসপ্লে এবং অনন্য ফোল্ডেড স্টেট ফোল্ডেবল ডিভাইসে নতুন ব্যবহারকারীর অভিজ্ঞতা প্রদান করে। আপনার অ্যাপকে ফোল্ড সচেতন করতে, Jetpack WindowManager লাইব্রেরি ব্যবহার করুন, যা ফোল্ড এবং হিঞ্জের মতো ফোল্ডেবল ডিভাইস উইন্ডো বৈশিষ্ট্যগুলির জন্য একটি API সারফেস প্রদান করে। যখন আপনার অ্যাপটি ফোল্ড সচেতন থাকে, তখন এটি ভাঁজ বা হিঞ্জের এলাকায় গুরুত্বপূর্ণ বিষয়বস্তু স্থাপন এড়াতে এর লেআউটটি অভিযোজিত করতে পারে এবং প্রাকৃতিক বিভাজক হিসাবে ভাঁজ এবং হিঞ্জ ব্যবহার করতে পারে।

কোনও ডিভাইস টেবিলটপ বা বুক পোজিশনের মতো কনফিগারেশন সমর্থন করে কিনা তা বোঝা বিভিন্ন লেআউট সমর্থন বা নির্দিষ্ট বৈশিষ্ট্য প্রদানের বিষয়ে সিদ্ধান্ত নিতে সহায়তা করতে পারে।

উইন্ডো তথ্য

Jetpack WindowManager-এর WindowInfoTracker ইন্টারফেস উইন্ডো লেআউটের তথ্য প্রকাশ করে। ইন্টারফেসের windowLayoutInfo() পদ্ধতি WindowLayoutInfo ডেটার একটি স্ট্রিম প্রদান করে যা আপনার অ্যাপকে একটি ফোল্ডেবল ডিভাইসের ভাঁজ অবস্থা সম্পর্কে অবহিত করে। WindowInfoTracker#getOrCreate() পদ্ধতি WindowInfoTracker এর একটি উদাহরণ তৈরি করে।

WindowManager Kotlin flows এবং Java কলব্যাক ব্যবহার করে WindowLayoutInfo ডেটা সংগ্রহের জন্য সহায়তা প্রদান করে।

কোটলিন প্রবাহিত হয়

WindowLayoutInfo ডেটা সংগ্রহ শুরু এবং বন্ধ করার জন্য, আপনি একটি পুনঃসূচনাযোগ্য জীবনচক্র-সচেতন কর্উটিন ব্যবহার করতে পারেন যেখানে repeatOnLifecycle কোড ব্লকটি কার্যকর করা হয় যখন জীবনচক্র কমপক্ষে STARTED হয় এবং জীবনচক্র STOPPED হলে বন্ধ হয়ে যায়। জীবনচক্রটি আবার STARTED হলে কোড ব্লকের কার্যকরকরণ স্বয়ংক্রিয়ভাবে পুনরায় শুরু হয়। নিম্নলিখিত উদাহরণে, কোড ব্লকটি WindowLayoutInfo ডেটা সংগ্রহ এবং ব্যবহার করে:

class DisplayFeaturesActivity : AppCompatActivity() {

    private lateinit var binding: ActivityDisplayFeaturesBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityDisplayFeaturesBinding.inflate(layoutInflater)
        setContentView(binding.root)

        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                WindowInfoTracker.getOrCreate(this@DisplayFeaturesActivity)
                    .windowLayoutInfo(this@DisplayFeaturesActivity)
                    .collect { newLayoutInfo ->
                        // Use newLayoutInfo to update the layout.
                    }
            }
        }
    }
}

জাভা কলব্যাকস

androidx.window:window-java নির্ভরতার মধ্যে অন্তর্ভুক্ত কলব্যাক সামঞ্জস্য স্তর আপনাকে Kotlin ফ্লো ব্যবহার না করেই WindowLayoutInfo আপডেট সংগ্রহ করতে সক্ষম করে। এই আর্টিফ্যাক্টটিতে WindowInfoTrackerCallbackAdapter ক্লাস অন্তর্ভুক্ত রয়েছে, যা WindowLayoutInfo আপডেটগুলি গ্রহণের জন্য কলব্যাক নিবন্ধন (এবং নিবন্ধনমুক্ত) সমর্থন করার জন্য একটি WindowInfoTracker অভিযোজিত করে, উদাহরণস্বরূপ:

public class SplitLayoutActivity extends AppCompatActivity {

    private WindowInfoTrackerCallbackAdapter windowInfoTracker;
    private ActivitySplitLayoutBinding binding;
    private final LayoutStateChangeCallback layoutStateChangeCallback =
            new LayoutStateChangeCallback();

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
       setContentView(binding.getRoot());

       windowInfoTracker =
                new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
   }

   @Override
   protected void onStart() {
       super.onStart();
       windowInfoTracker.addWindowLayoutInfoListener(
                this, Runnable::run, layoutStateChangeCallback);
   }

   @Override
   protected void onStop() {
       super.onStop();
       windowInfoTracker
           .removeWindowLayoutInfoListener(layoutStateChangeCallback);
   }

   class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
       @Override
       public void accept(WindowLayoutInfo newLayoutInfo) {
           SplitLayoutActivity.this.runOnUiThread( () -> {
               // Use newLayoutInfo to update the layout.
           });
       }
   }
}

আরএক্সজাভা সাপোর্ট

যদি আপনি ইতিমধ্যেই RxJava (সংস্করণ 2 বা 3 ) ব্যবহার করে থাকেন, তাহলে আপনি এমন আর্টিফ্যাক্টের সুবিধা নিতে পারেন যা আপনাকে Kotlin ফ্লো ব্যবহার না করেই WindowLayoutInfo আপডেট সংগ্রহ করতে Observable বা Flowable ব্যবহার করতে সক্ষম করে।

androidx.window:window-rxjava2 এবং androidx.window:window-rxjava3 নির্ভরতা দ্বারা প্রদত্ত সামঞ্জস্য স্তরের মধ্যে রয়েছে WindowInfoTracker#windowLayoutInfoFlowable() এবং WindowInfoTracker#windowLayoutInfoObservable() পদ্ধতি, যা আপনার অ্যাপকে WindowLayoutInfo আপডেট পেতে সক্ষম করে, উদাহরণস্বরূপ:

class RxActivity: AppCompatActivity {

    private lateinit var binding: ActivityRxBinding

    private var disposable: Disposable? = null
    private lateinit var observable: Observable<WindowLayoutInfo>

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
       setContentView(binding.getRoot());

        // Create a new observable.
        observable = WindowInfoTracker.getOrCreate(this@RxActivity)
            .windowLayoutInfoObservable(this@RxActivity)
   }

   @Override
   protected void onStart() {
       super.onStart();

        // Subscribe to receive WindowLayoutInfo updates.
        disposable?.dispose()
        disposable = observable
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { newLayoutInfo ->
            // Use newLayoutInfo to update the layout.
        }
   }

   @Override
   protected void onStop() {
       super.onStop();

        // Dispose of the WindowLayoutInfo observable.
        disposable?.dispose()
   }
}

ভাঁজযোগ্য ডিসপ্লের বৈশিষ্ট্য

Jetpack WindowManager-এর WindowLayoutInfo ক্লাসটি একটি ডিসপ্লে উইন্ডোর বৈশিষ্ট্যগুলিকে DisplayFeature উপাদানের তালিকা হিসাবে উপলব্ধ করে।

FoldingFeature হল এক ধরণের DisplayFeature যা ফোল্ডেবল ডিসপ্লে সম্পর্কে তথ্য প্রদান করে, যার মধ্যে নিম্নলিখিত বৈশিষ্ট্যগুলি অন্তর্ভুক্ত রয়েছে:

  • state : ডিভাইসের ভাঁজ করা অবস্থা, FLAT অথবা HALF_OPENED

  • orientation : ভাঁজ বা কব্জার ওরিয়েন্টেশন, HORIZONTAL বা VERTICAL

  • occlusionType : ভাঁজ বা কব্জা ডিসপ্লের কিছু অংশ লুকিয়ে রাখে কিনা, NONE নাকি FULL

  • isSeparating : ভাঁজ বা কব্জা দুটি লজিক্যাল ডিসপ্লে এরিয়া তৈরি করে কিনা, সত্য নাকি মিথ্যা

একটি ভাঁজযোগ্য ডিভাইস যা HALF_OPENED , সর্বদা isSeparating কে সত্য বলে রিপোর্ট করে কারণ স্ক্রিনটি দুটি ডিসপ্লে এলাকায় বিভক্ত। এছাড়াও, যখন অ্যাপ্লিকেশনটি উভয় স্ক্রিন জুড়ে বিস্তৃত থাকে তখন ডুয়াল-স্ক্রিন ডিভাইসে isSeparating সর্বদা সত্য বলে রিপোর্ট করে।

FoldingFeature bounds প্রপার্টি ( DisplayFeature থেকে উত্তরাধিকারসূত্রে প্রাপ্ত) একটি ভাঁজ বৈশিষ্ট্যের বাউন্ডিং আয়তক্ষেত্রকে প্রতিনিধিত্ব করে যেমন একটি ভাঁজ বা কব্জা। বৈশিষ্ট্যের সাপেক্ষে স্ক্রিনে উপাদানগুলি স্থাপন করতে বাউন্ডগুলি ব্যবহার করা যেতে পারে:

কোটলিন

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    lifecycleScope.launch(Dispatchers.Main) {
        lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
            // Safely collects from WindowInfoTracker when the lifecycle is
            // STARTED and stops collection when the lifecycle is STOPPED.
            WindowInfoTracker.getOrCreate(this@MainActivity)
                .windowLayoutInfo(this@MainActivity)
                .collect { layoutInfo ->
                    // New posture information.
                    val foldingFeature = layoutInfo.displayFeatures
                        .filterIsInstance<FoldingFeature>()
                        .firstOrNull()
                    // Use information from the foldingFeature object.
                }
        }
    }
}

জাভা

private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private final LayoutStateChangeCallback layoutStateChangeCallback =
                new LayoutStateChangeCallback();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    // ...
    windowInfoTracker =
            new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}

@Override
protected void onStart() {
    super.onStart();
    windowInfoTracker.addWindowLayoutInfoListener(
            this, Runnable::run, layoutStateChangeCallback);
}

@Override
protected void onStop() {
    super.onStop();
    windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}

class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
    @Override
    public void accept(WindowLayoutInfo newLayoutInfo) {
        // Use newLayoutInfo to update the Layout.
        List<DisplayFeature> displayFeatures = newLayoutInfo.getDisplayFeatures();
        for (DisplayFeature feature : displayFeatures) {
            if (feature instanceof FoldingFeature) {
                // Use information from the feature object.
            }
        }
    }
}

টেবিলটপ ভঙ্গি

FoldingFeature অবজেক্টে অন্তর্ভুক্ত তথ্য ব্যবহার করে, আপনার অ্যাপটি টেবিলটপের মতো ভঙ্গি সমর্থন করতে পারে, যেখানে ফোনটি কোনও পৃষ্ঠের উপর বসে থাকে, কব্জাটি একটি অনুভূমিক অবস্থানে থাকে এবং ভাঁজযোগ্য স্ক্রিনটি অর্ধেক খোলা থাকে।

ট্যাবলেটপ পোজেশন ব্যবহারকারীদের ফোন হাতে না ধরেই তাদের ফোন চালানোর সুবিধা প্রদান করে। ট্যাবলেটপ পোজেশন মিডিয়া দেখা, ছবি তোলা এবং ভিডিও কল করার জন্য দুর্দান্ত।

চিত্র ১. টেবিলটপ ভঙ্গিতে একটি ভিডিও প্লেয়ার অ্যাপ—স্ক্রিনের উল্লম্ব অংশে ভিডিও; অনুভূমিক অংশে প্লেব্যাক নিয়ন্ত্রণ।

ডিভাইসটি টেবিলটপ ভঙ্গিতে আছে কিনা তা নির্ধারণ করতে FoldingFeature.State এবং FoldingFeature.Orientation ব্যবহার করুন:

কোটলিন

fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
}

জাভা

boolean isTableTopPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}

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

অ্যান্ড্রয়েড ১৫ (এপিআই লেভেল ৩৫) এবং তার উচ্চতর সংস্করণে, ডিভাইসের বর্তমান অবস্থা নির্বিশেষে, কোনও ডিভাইস ট্যাবলেটপ পোজিশন সমর্থন করে কিনা তা সনাক্ত করার জন্য আপনি একটি সিঙ্ক্রোনাস এপিআই ব্যবহার করতে পারেন।

API ডিভাইস দ্বারা সমর্থিত ভঙ্গিগুলির একটি তালিকা প্রদান করে। যদি তালিকায় টেবিলটপ ভঙ্গি থাকে, তাহলে আপনি ভঙ্গি সমর্থন করার জন্য আপনার অ্যাপ লেআউটকে বিভক্ত করতে পারেন এবং ট্যাবলেটপ এবং পূর্ণ-স্ক্রিন লেআউটের জন্য আপনার অ্যাপ UI তে A/B পরীক্ষা চালাতে পারেন।

কোটলিন

if (WindowSdkExtensions.getInstance().extensionsVersion >= 6) {
    val postures = WindowInfoTracker.getOrCreate(context).supportedPostures
    if (postures.contains(TABLE_TOP)) {
        // Device supports tabletop posture.
   }
}

জাভা

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    List<SupportedPosture> postures = WindowInfoTracker.getOrCreate(context).getSupportedPostures();
    if (postures.contains(SupportedPosture.TABLETOP)) {
        // Device supports tabletop posture.
    }
}

উদাহরণ

বইয়ের ভঙ্গি

আরেকটি অনন্য ভাঁজযোগ্য বৈশিষ্ট্য হল বইয়ের ভঙ্গি, যেখানে ডিভাইসটি অর্ধেক খোলা থাকে এবং কব্জাটি উল্লম্ব থাকে। ই-বই পড়ার জন্য বইয়ের ভঙ্গি দুর্দান্ত। দুই পৃষ্ঠার লেআউটের সাহায্যে ভাঁজ করা যায় এমন একটি বড় স্ক্রিনে যা আবদ্ধ বইয়ের মতো খোলা থাকে, বইয়ের ভঙ্গি একটি বাস্তব বই পড়ার অভিজ্ঞতা ধারণ করে।

হ্যান্ডস-ফ্রি ছবি তোলার সময় যদি আপনি ভিন্ন আকৃতির অনুপাত ধারণ করতে চান, তাহলে এটি ফটোগ্রাফির জন্যও ব্যবহার করা যেতে পারে।

টেবিলটপ ভঙ্গির জন্য ব্যবহৃত একই কৌশল ব্যবহার করে বইয়ের ভঙ্গি বাস্তবায়ন করুন। একমাত্র পার্থক্য হল কোডটি পরীক্ষা করা উচিত যে ভাঁজ বৈশিষ্ট্যের অভিযোজন অনুভূমিকের পরিবর্তে উল্লম্ব:

কোটলিন

fun isBookPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.VERTICAL
}

জাভা

boolean isBookPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.VERTICAL);
}

জানালার আকার পরিবর্তন

ডিভাইস কনফিগারেশন পরিবর্তনের ফলে একটি অ্যাপের ডিসপ্লে এরিয়া পরিবর্তিত হতে পারে, উদাহরণস্বরূপ, যখন ডিভাইসটি ভাঁজ করা হয় বা খোলা হয়, ঘোরানো হয়, অথবা মাল্টি-উইন্ডো মোডে একটি উইন্ডোর আকার পরিবর্তন করা হয়।

Jetpack WindowManager WindowMetricsCalculator ক্লাস আপনাকে বর্তমান এবং সর্বোচ্চ উইন্ডো মেট্রিক্স পুনরুদ্ধার করতে সক্ষম করে। API লেভেল 30-এ প্রবর্তিত WindowMetrics প্ল্যাটফর্মের মতো, WindowManager WindowMetrics উইন্ডো বাউন্ড প্রদান করে, কিন্তু API লেভেল 14 পর্যন্ত ব্যাকওয়ার্ড সামঞ্জস্যপূর্ণ।

উইন্ডো সাইজ ক্লাস ব্যবহার করুন দেখুন।

অতিরিক্ত সম্পদ

নমুনা

  • জেটপ্যাক উইন্ডো ম্যানেজার : জেটপ্যাক উইন্ডো ম্যানেজার লাইব্রেরি কীভাবে ব্যবহার করবেন তার উদাহরণ
  • জেটকাস্টার : কম্পোজ সহ ট্যাবলেটপ পোশ্চার বাস্তবায়ন

কোডল্যাব