উইন্ডো ইনসেট সেট-আপ করা

আপনার অ্যাক্টিভিটি একবার সমস্ত ইনসেট হ্যান্ডেল করার কন্ট্রোল নিলে, আপনি Compose API ব্যবহার করে যাচাই করতে পারবেন যে কন্টেন্ট অস্পষ্ট নয় এবং ইন্ট্যার‍্যাক্ট করা যায় এমন এলিমেন্ট সিস্টেম UI-এর সাথে ওভারল্যাপ করছে না। এছাড়াও, এই API ইনসেট পরিবর্তন সহ আপনার অ্যাপের লেআউট সিঙ্ক করে।

প্যাডিং বা সাইজ মডিফায়ার ব্যবহার করে ইনসেট ম্যানেজ করা

যেমন, আপনার সম্পূর্ণ অ্যাপের কন্টেন্টে ইনসেট প্রয়োগ করার এটি হল সবচেয়ে প্রাথমিক পদ্ধতি:

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

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

এই স্নিপেটটি অ্যাপের সম্পূর্ণ কন্টেন্টের চারপাশে প্যাডিং হিসেবে safeDrawing উইন্ডো ইনসেট প্রয়োগ করে। এটি নিশ্চিত করে যে ইন্টার‍্যাক্ট করা যায় এমন এলিমেন্ট সিস্টেম UI-এর সাথে ওভারল্যাপ করবে না। এর অর্থ হল, এজ-টু-এজ এফেক্ট পাওয়ার জন্য কোনও অ্যাপই সিস্টেম UI-এর পিছনে ড্র করবে না। সম্পূর্ণ উইন্ডোর সদ্ব্যবহার করতে, স্ক্রিন-বাই-স্ক্রিন বা কম্পোনেন্ট-বাই-কম্পোনেন্ট ভিত্তিতে ইনসেট কোথায় প্রয়োগ করা হবে তা আপনাকে ফাইন-টিউন করতে হবে।

এইসব ইনসেট ধরনের সবকটিই IME অ্যানিমেশন দিয়ে অটোমেটিক অ্যানিমেট করা হয় যা API 21-এ ব্যাকপোর্ট করা হয়েছে। এর ফলে, এইসব ইনসেট ব্যবহার করে আপনার সব লেআউটও ইনসেট ভ্যালু পরিবর্তন হওয়ার সাথে সাথে অটোমেটিক অ্যানিমেট হয়ে যায়।

আপনার কম্পোজ করার মতো লেআউট অ্যাডজাস্ট করতে ইনসেট ম্যানেজ করার তিনটি উপায় আছে:

প্যাডিং মডিফায়ার

Modifier.windowInsetsPadding(windowInsets: WindowInsets), Modifier.padding-এর মতো কাজ করে প্যাডিং হিসেবে প্রদত্ত উইন্ডো ইনসেট প্রয়োগ করে। যেমন, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) ৪টি দিকেই প্যাডিং হিসেবে নিরাপদ ড্রয়িং ইনসেট প্রয়োগ করে।

এছাড়াও, সবচেয়ে সাধারণ ইনসেট ধরনের জন্য বেশ কিছু বিল্ট-ইন ইউটিলিটি পদ্ধতি রয়েছে। Modifier.safeDrawingPadding() হল এমন একটি পদ্ধতি যা Modifier.windowInsetsPadding(WindowInsets.safeDrawing)-এর সমতুল্য। অন্যান্য ইনসেট ধরনের জন্য একই ধরনের মডিফায়ার আছে।

ইনসেট সাইজ মডিফায়ার

নিম্নলিখিত মডিফায়ারগুলি ইনসেটের সাইজ অনুযায়ী কম্পোনেন্টের সাইজ সেট করে উইন্ডো ইনসেটের পরিমাণ প্রয়োগ করে:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

width হিসেবে windowInsets-এর স্টার্ট সাইড প্রয়োগ করে (যেমন Modifier.width)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

width হিসেবে windowInsets-এর শেষ দিকটি প্রয়োগ করে (যেমন Modifier.width)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

উচ্চতা হিসেবে windowInsets-এর উপরের দিকটি প্রয়োগ করে (যেমন Modifier.height)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

উচ্চতা হিসেবে windowInsets-এর নিচের দিকটি প্রয়োগ করে (যেমন Modifier.height)

ইনসেটের স্পেস দখল করে এমন Spacer-এর সাইজ নির্ধারণ করার জন্য এইসব মডিফায়ার বিশেষভাবে উপযোগী:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

ইনসেট কনজাম্পশন

ইনসেট প্যাডিং মডিফায়ার (windowInsetsPadding এবং হেল্পার যেমন safeDrawingPadding) অটোমেটিক ইনসেটের সেই অংশটি ব্যবহার করে যা প্যাডিং হিসেবে প্রয়োগ করা হয়। কম্পোজিশন ট্রি-তে আরও গভীরে যাওয়ার সময়, নেস্টেড ইনসেট প্যাডিং মডিফায়ার ও ইনসেট সাইজ মডিফায়ার জানে যে ইনসেটের কিছু অংশ আউটার ইনসেট প্যাডিং মডিফায়ার আগেই ব্যবহার করে নিয়েছে এবং ইনসেটের একই অংশ একাধিকবার ব্যবহার করা এড়িয়ে যায়, এর ফলে অতিরিক্ত স্পেস তৈরি হয় না।

ইনসেট সাইজ মডিফায়াররা ইনসেট ইতিমধ্যেই ব্যবহার করা হয়ে থাকলে, ইনসেটের একই অংশ একাধিকবার ব্যবহার করা এড়িয়ে যায়। তবে, যেহেতু তারা সরাসরি নিজেদের সাইজ পরিবর্তন করছে, তাই তারা ইনসেট ব্যবহার করে না।

এর ফলে, নেস্টিং প্যাডিং মডিফায়ার প্রতিটি কম্পোজ করার উপযুক্ত আইটেমে প্রয়োগ করা প্যাডিংয়ের পরিমাণ অটোমেটিক পরিবর্তন করে দেয়।

আগের LazyColumn উদাহরণটি দেখলে, imePadding মডিফায়ার দিয়ে LazyColumn-এর সাইজ পরিবর্তন করা হচ্ছে। LazyColumn-এর মধ্যে, শেষ আইটেমটি সিস্টেম বারের নিচের দিকের উচ্চতার সমান সাইজের হয়:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

IME বন্ধ থাকলে, imePadding() কোনও প্যাডিং প্রয়োগ করে না। এর ফলে, কোনও ইনসেট ব্যবহার করা হয় না এবং Spacer উচ্চতা নিচের সিস্টেম বারের সাথে ম্যাচ করে।

IME খুললে, IME ইনসেট অ্যানিমেট করে IME-এর সাইজের সাথে ম্যাচ করে এবং IME খোলার সাথে সাথে imePadding() মডিফায়ার LazyColumn-এর সাইজ পরিবর্তন করতে বটম প্যাডিং প্রয়োগ করা শুরু করে। imePadding() মডিফায়ার বটম প্যাডিং প্রয়োগ করা শুরু করলে সেটি ইনসেটের সেই পরিমাণও ব্যবহার করা শুরু করে। তাই, সিস্টেম বারগুলির স্পেসিংয়ের অংশ হিসেবে Spacer-এর উচ্চতা কমতে শুরু করে, কারণ imePadding() মডিফায়ার আগেই এটি প্রয়োগ করেছে। imePadding() মডিফায়ারটি সিস্টেম বারের চেয়ে বেশি নিচের প্যাডিং প্রয়োগ করলে, Spacer-এর উচ্চতা শূন্য হয়ে যায়।

IME বন্ধ হয়ে গেলে, পরিবর্তনগুলি বিপরীত ক্রমে ঘটে: imePadding() বটম সিস্টেম বারের থেকে কম প্রয়োগ করার ফলে Spacer শূন্য উচ্চতা থেকে প্রসারিত হয়। সবশেষে, IME সম্পূর্ণভাবে অ্যানিমেট হয়ে বেরিয়ে গেলে Spacer-এর উচ্চতা সিস্টেম বারের সাথে মিলে যায়।

ছবি ২. TextField
সহ এজের সাথে এজ মিলে যাওয়া লেজি কলাম।
লুকিয়ে রাখতে পারে।

এই আচরণটি সমস্ত windowInsetsPadding মডিফায়ারের মধ্যে কমিউনিকেশনের মাধ্যমে সম্পন্ন হয় এবং এটি আরও কয়েকটি উপায়ে প্রভাবিত হতে পারে।

Modifier.consumeWindowInsets(insets: WindowInsets)-ও Modifier.windowInsetsPadding-এর মতো ইনসেট ব্যবহার করে, তবে এটি ব্যবহার করা ইনসেটকে প্যাডিং হিসেবে প্রয়োগ করে না। ইনসেট সাইজ মডিফায়ারের সাথে এটি ব্যবহার করা হলে, এটি সিবলিংদের বোঝাতে সাহায্য করে যে একটি নির্দিষ্ট পরিমাণ ইনসেট আগে থেকেই ব্যবহার করা হয়েছে:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) WindowInsets আর্গুমেন্ট সহ ভার্সনের মতো আচরণ করে, কিন্তু ব্যবহার করার জন্য একটি আর্বিট্রারি PaddingValues নেয়। ইনসেট প্যাডিং মডিফায়ার ছাড়া অন্য কোনও মেকানিজম, যেমন সাধারণ Modifier.padding বা নির্দিষ্ট হাইট স্পেসার ব্যবহার করে প্যাডিং বা স্পেসিং দেওয়া হলে, এই পদ্ধতি বাচ্চাদের জানানোর জন্য উপযোগী:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

যেসব ক্ষেত্রে কাঁচা উইন্ডো ইনসেট ব্যবহারের প্রয়োজন হয়, সেখানে সরাসরি WindowInsets ভ্যালু ব্যবহার করুন অথবা WindowInsets.asPaddingValues() ব্যবহার করে ইনসেটের PaddingValues ভ্যালু রিটার্ন করুন যেগুলি ব্যবহারের ফলে প্রভাবিত হয় না। তবে, নিম্নলিখিত সতর্কতাগুলির কারণে, যেখানেই সম্ভব উইন্ডো ইনসেট প্যাডিং মডিফায়ার এবং উইন্ডো ইনসেট সাইজ মডিফায়ার ব্যবহার করুন।

ইনসেট ও Jetpack Compose ফেজ

ইনসেট আপডেট ও অ্যানিমেট করার জন্য Compose, অন্তর্নিহিত AndroidX কোর API ব্যবহার করে, যা ইনসেট ম্যানেজ করার জন্য অন্তর্নিহিত প্ল্যাটফর্ম API ব্যবহার করে। সেই প্ল্যাটফর্মের আচরণগত কারণে, ইনসেটের সাথে Jetpack Compose-এর ফেজের একটি বিশেষ সম্পর্ক আছে।

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