mediaQuery ব্যবহার করে অ্যাডাপ্টিভ লেআউটের জন্য তথ্য অনুসন্ধান করুন

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

  • জানালার ভঙ্গি
  • পয়েন্টিং ডিভাইসের নির্ভুলতা
  • কিবোর্ডের ধরন
  • ডিভাইসটি ক্যামেরা এবং মাইক্রোফোন সমর্থন করে কিনা
  • ব্যবহারকারী এবং ডিভাইসের ডিসপ্লের মধ্যে দূরত্ব

যেহেতু তথ্য গতিশীলভাবে আপডেট হয়, তাই আপনাকে এটি পর্যবেক্ষণ করতে হবে এবং কোনো আপডেট ঘটলে পুনর্গঠন শুরু করতে হবে। mediaQuery ফাংশনটি তথ্য পুনরুদ্ধারের খুঁটিনাটি বিষয়গুলো আড়াল করে এবং আপনাকে লেআউট আপডেট শুরু করার শর্ত নির্ধারণের উপর মনোযোগ দিতে সাহায্য করে। নিচের উদাহরণটি ফোল্ডেবলটির ভঙ্গি টেবিলটপ হলে লেআউটটিকে TabletopLayout এ পরিবর্তন করে দেয়:

@Composable
fun VideoPlayer(
    // ...
) {
    // ...
            if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
                TabletopLayout()
            } else {
                FlatLayout()
            }
    // ...
}

mediaQuery ফাংশনটি সক্রিয় করুন

mediaQuery ফাংশনটি সক্রিয় করতে, ComposeUiFlags অবজেক্টের isMediaQueryIntegrationEnabled অ্যাট্রিবিউটটিকে true তে সেট করুন:

class MyApplication : Application() {
    override fun onCreate() {
        ComposeUiFlags.isMediaQueryIntegrationEnabled = true
        super.onCreate()
    }
}

প্যারামিটার সহ একটি শর্ত সংজ্ঞায়িত করুন

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

প্যারামিটার মান প্রকার বর্ণনা
windowWidth Dp বর্তমান উইন্ডোর প্রস্থ (ডিপি-তে)।
windowHeight Dp বর্তমান উইন্ডোর উচ্চতা (ডিপি-তে)।
windowPosture UiMediaScope.Posture অ্যাপ্লিকেশন উইন্ডোটির বর্তমান অবস্থা।
pointerPrecision UiMediaScope.PointerPrecision উপলব্ধ পয়েন্টিং ডিভাইসগুলোর মধ্যে সর্বোচ্চ নির্ভুলতা।
keyboardKind UiMediaScope.KeyboardKind উপলব্ধ বা সংযুক্ত কিবোর্ডের ধরন।
hasCamera Boolean ডিভাইসটিতে ক্যামেরাটি সমর্থিত কিনা।
hasMicrophone Boolean ডিভাইসটিতে মাইক্রোফোনটি সমর্থিত কিনা।
viewingDistance UiMediaScope.ViewingDistance ব্যবহারকারী এবং ডিভাইসের স্ক্রিনের মধ্যে সাধারণ দূরত্ব।

একটি UiMediaScope অবজেক্ট প্যারামিটারগুলোর মান নির্ধারণ করে। mediaQuery ফাংশনটি UiMediaScope অবজেক্টটি অ্যাক্সেস করার জন্য LocalUiMediaScope.current ব্যবহার করে, যা ডিভাইসের বর্তমান সক্ষমতা এবং প্রেক্ষাপটকে উপস্থাপন করে। যখন কোনো পরিবর্তন করা হয়, যেমন ব্যবহারকারী ডিভাইসের ভঙ্গি পরিবর্তন করলে, এই অবজেক্টটি গতিশীলভাবে আপডেট হয়। এরপর mediaQuery ফাংশনটি আপডেট করা UiMediaScope অবজেক্ট দিয়ে query ল্যাম্বডা মূল্যায়ন করে এবং একটি বুলিয়ান মান রিটার্ন করে। উদাহরণস্বরূপ, নিম্নলিখিত কোড স্নিপেটটি windowPosture প্যারামিটারের মানের উপর ভিত্তি করে TabletopLayout এবং FlatLayout মধ্যে একটিকে বেছে নেয়।

@Composable
fun VideoPlayer(
    // ...
) {
    // ...
            if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
                TabletopLayout()
            } else {
                FlatLayout()
            }
    // ...
}

জানালার আকারের উপর ভিত্তি করে সিদ্ধান্ত নিন

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

derivedMediaQuery ফাংশনটি query ল্যাম্বডা মূল্যায়ন করে এবং ফলাফলটিকে একটি derivedStateOf মধ্যে আবদ্ধ করে। যেহেতু windowWidth এবং windowHeight ঘন ঘন আপডেট হতে পারে, তাই query ল্যাম্বডায় এই প্যারামিটারগুলো উল্লেখ করার সময় mediaQuery ফাংশনের পরিবর্তে derivedMediaQuery ফাংশনটি কল করুন।

val narrowerThanMedium by derivedMediaQuery {
    windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp
}
val narrowerThanExpanded by derivedMediaQuery {
    windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp
}
when {
    narrowerThanMedium -> SinglePaneLayout()
    narrowerThanExpanded -> TwoPaneLayout()
    else -> ThreePaneLayout()
}

চিত্র ১। উইন্ডোর প্রস্থ অনুযায়ী লেআউট আপডেট করা হয়।

উইন্ডোর অবস্থান অনুযায়ী লেআউট আপডেট করুন।

windowPosture প্যারামিটারটি একটি UiMediaScope.Posture অবজেক্ট হিসেবে বর্তমান উইন্ডোর ভঙ্গি বর্ণনা করে। আপনি UiMediaScope.Posture ক্লাসে সংজ্ঞায়িত মানগুলির সাথে প্যারামিটারটি তুলনা করে বর্তমান ভঙ্গিটি পরীক্ষা করতে পারেন। নিম্নলিখিত উদাহরণটি উইন্ডোর ভঙ্গি অনুযায়ী লেআউট পরিবর্তন করে:

when {
    mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
}

উপলব্ধ পয়েন্টিং ডিভাইসটির নির্ভুলতা যাচাই করুন।

একটি উচ্চ নির্ভুলতা সম্পন্ন পয়েন্টিং ডিভাইস ব্যবহারকারীদের একটি UI এলিমেন্টকে নির্ভুলভাবে নির্দেশ করতে সাহায্য করে। একটি পয়েন্টিং ডিভাইসের নির্ভুলতা ডিভাইসটির ধরনের উপর নির্ভর করে।

pointerPrecision প্যারামিটারটি মাউস এবং টাচস্ক্রিনের মতো উপলব্ধ পয়েন্টিং ডিভাইসগুলোর নির্ভুলতা বর্ণনা করে। UiMediaScope.PointerPrecision ক্লাসে চারটি মান সংজ্ঞায়িত করা আছে: Fine , Coarse , Blunt এবং NoneNone এর অর্থ হলো কোনো পয়েন্টিং ডিভাইস উপলব্ধ নেই। নির্ভুলতার পরিসর সর্বোচ্চ থেকে সর্বনিম্ন এই ক্রমে থাকে: Fine , Coarse এবং Blunt

যদি একাধিক পয়েন্টিং ডিভাইস উপলব্ধ থাকে এবং তাদের প্রিসিশন ভিন্ন হয়, তবে প্যারামিটারটি সর্বোচ্চটির মাধ্যমে সমাধান করা হয়। উদাহরণস্বরূপ, যদি দুটি পয়েন্টিং ডিভাইস থাকে — একটি Fine প্রিসিশন ডিভাইস এবং একটি Blunt প্রিসিশন ডিভাইস — তাহলে pointerPrecision প্যারামিটারের মান হবে Fine

নিম্নলিখিত উদাহরণটি দেখায় যে, ব্যবহারকারী যখন কম নির্ভুলতার কোনো পয়েন্টিং ডিভাইস ব্যবহার করেন, তখন বাটনটি বড় হয়:

if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) {
    LargeSizeButton()
} else {
    NormalSizeButton()
}

উপলব্ধ কীবোর্ডের ধরন পরীক্ষা করুন

keyboardKind প্যারামিটারটি উপলব্ধ কিবোর্ডগুলোর ধরন নির্দেশ করে: Physical , Virtual , এবং None । যদি একটি অন-স্ক্রিন কিবোর্ড প্রদর্শিত হয় এবং একই সময়ে একটি হার্ডওয়্যার কিবোর্ডও উপলব্ধ থাকে, তাহলে প্যারামিটারটি Physical হিসেবে নির্ধারিত হয়। যদি কোনোটিই শনাক্ত না হয়, তাহলে প্যারামিটারটির মান হয় None । নিচের উদাহরণটিতে এমন একটি বার্তা দেখানো হয়েছে, যা কোনো কিবোর্ড শনাক্ত না হলে ব্যবহারকারীদের একটি কিবোর্ড সংযোগ করার পরামর্শ দেয়:

if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) {
    SuggestKeyboardConnect()
}

ডিভাইসটি ক্যামেরা এবং মাইক্রোফোন সমর্থন করে কিনা তা পরীক্ষা করুন।

কিছু ডিভাইস ক্যামেরা বা মাইক্রোফোন সমর্থন করে না। ডিভাইসটি ক্যামেরা এবং মাইক্রোফোন সমর্থন করে কিনা তা আপনি hasCamera প্যারামিটার এবং hasMicrophone প্যারামিটার ব্যবহার করে পরীক্ষা করতে পারেন। নিচের উদাহরণটিতে দেখানো হয়েছে, ডিভাইসটি ক্যামেরা এবং মাইক্রোফোন সমর্থন করলে সেগুলোর জন্য কোন বাটনগুলো ব্যবহার করতে হবে:

Row {
    OutlinedTextField(state = rememberTextFieldState())
    // Show the MicButton when the device supports a microphone.
    if (mediaQuery { hasMicrophone }) {
        MicButton()
    }
    // Show the CameraButton when the device supports a camera.
    if (mediaQuery { hasCamera }) {
        CameraButton()
    }
}

আনুমানিক দেখার দূরত্ব দিয়ে UI সামঞ্জস্য করুন

দেখার দূরত্ব এমন একটি বিষয় যা লেআউট নির্ধারণে সাহায্য করে। ব্যবহারকারী যদি দূর থেকে অ্যাপটি ব্যবহার করেন, তবে তিনি টেক্সট এবং UI এলিমেন্টগুলোকে আরও বড় দেখতে চাইবেন। viewingDistance প্যারামিটারটি ডিভাইসের ধরন এবং এর সাধারণ ব্যবহারের প্রেক্ষাপটের উপর ভিত্তি করে দেখার দূরত্বের একটি আনুমানিক ধারণা দেয়।

UiMediaScope.ViewingDistance ক্লাসে তিনটি মান সংজ্ঞায়িত করা আছে: Near , Medium , এবং FarNear মানে হলো স্ক্রিনটি খুব কাছে আছে, এবং Far মানে হলো ডিভাইসটি দূর থেকে দেখা হচ্ছে। নিচের উদাহরণটি দেখার দূরত্ব Far বা Medium হলে ফন্টের আকার বাড়িয়ে দেয়:

val fontSize = when {
    mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp
    mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp
    else -> 16.sp
}

একটি UI উপাদানের পূর্বরূপ দেখুন

UI কম্পোনেন্টগুলোর প্রিভিউ দেখার জন্য আপনি কম্পোজেবল ফাংশনগুলোর মধ্যে mediaQuery এবং derivedMediaQuery ফাংশনগুলো কল করতে পারেন। নিচের কোড স্নিপেটটি windowPosture প্যারামিটারের মানের উপর ভিত্তি করে TabletopLayout এবং FlatLayout এর মধ্যে একটিকে বেছে নেয়। TabletopLayout এর প্রিভিউ দেখার জন্য windowPosture প্যারামিটারটি UiMediaScope.Posture.Tabletop হওয়া উচিত।

when {
    mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
}

mediaQuery এবং derivedMediaQuery ফাংশনগুলো একটি UiMediaScope অবজেক্টের মধ্যে প্রদত্ত query ল্যাম্বডা মূল্যায়ন করে, যা LocalUiMediaScope.current হিসেবে সরবরাহ করা হয়। আপনি নিম্নলিখিত ধাপগুলো অনুসরণ করে এটিকে ওভাররাইড করতে পারেন:

  1. mediaQuery ফাংশনটি সক্রিয় করুন।
  2. একটি কাস্টম অবজেক্ট সংজ্ঞায়িত করুন যা UiMediaScope ইন্টারফেসটি ইমপ্লিমেন্ট করে।
  3. CompositionLocalProvider ফাংশনটি ব্যবহার করে কাস্টম অবজেক্টটিকে LocalUiMediaScope এ সেট করুন।
  4. CompositionLocalProvider ফাংশনের content ল্যাম্বডাতে প্রিভিউ করার জন্য কম্পোজেবলটি কল করুন।

আপনি নিম্নলিখিত উদাহরণটির সাহায্যে TabletopLayout প্রিভিউ দেখতে পারেন:

@Preview
@Composable
fun PreviewLayoutForTabletop() {
    // Step 1: Enable the mediaQuery function
    ComposeUiFlags.isMediaQueryIntegrationEnabled = true

    val currentUiMediaScope = LocalUiMediaScope.current
    // Step 2: Define a custom object implementing the UiMediaScope interface.
    // The object overrides the windowPosture parameter.
    // The resolution of the remaining parameters is deferred to the currentUiMediaScope object.
    val uiMediaScope = remember(currentUiMediaScope) {
        object : UiMediaScope by currentUiMediaScope {
            override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop
        }
    }

    // Step 3: Set the object to the LocalUiMediaScope.
    CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) {
        // Step 4: Call the composable to preview.
        when {
            mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
            mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
            mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
        }
    }
}