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 एक्सप्रेशन जैसी कंडिशनल ब्रांच की मदद से, लेआउट तय किया जा सकता है. टेबल 1 में, 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 lambda का आकलन करता है और बूलियन वैल्यू दिखाता है. उदाहरण के लिए, यहां दिया गया स्निपेट windowPosture पैरामीटर की वैल्यू के आधार पर, TabletopLayout और FlatLayout में से किसी एक को चुनता है.

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

विंडो के साइज़ के आधार पर फ़ैसला लेना

विंडो साइज़ क्लास, व्यूपोर्ट ब्रेकपॉइंट का एक सेट होता है. इसकी मदद से, अडैप्टिव लेआउट डिज़ाइन किए जा सकते हैं, डेवलप किए जा सकते हैं, और टेस्ट किए जा सकते हैं. मौजूदा विंडो के साइज़ को दिखाने वाले दो पैरामीटर की तुलना, विंडो साइज़ क्लास में तय किए गए थ्रेशोल्ड से की जा सकती है. यहां दिए गए उदाहरण में, विंडो की चौड़ाई के हिसाब से पैनल की संख्या बदली गई है. WindowSizeClass क्लास में, विंडो साइज़ क्लास की थ्रेशोल्ड के लिए कॉन्सटेंट होते हैं (इमेज 1).

derivedMediaQuery फ़ंक्शन, query lambda का आकलन करता है और नतीजे को derivedStateOf में रैप करता है. windowWidth और windowHeight अक्सर अपडेट हो सकते हैं. इसलिए, query lambda में उन पैरामीटर को रेफ़र करते समय, 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()
}

उपलब्ध पॉइंटिंग डिवाइस की सटीक जानकारी देखना

हाई प्रिसिज़न पॉइंटिंग डिवाइस की मदद से, उपयोगकर्ता किसी यूज़र इंटरफ़ेस (यूआई) एलिमेंट को सटीक तरीके से पॉइंट कर सकते हैं. पॉइंटिंग डिवाइस कितना सटीक है, यह डिवाइस के टाइप पर निर्भर करता है.

pointerPrecision पैरामीटर, उपलब्ध पॉइंटिंग डिवाइसों की सटीक जानकारी देता है. जैसे, माउस और टचस्क्रीन. UiMediaScope.PointerPrecision क्लास में चार वैल्यू तय की गई हैं: Fine, Coarse, Blunt, और None. None का मतलब है कि कोई पॉइंटिंग डिवाइस उपलब्ध नहीं है. सटीक जानकारी की रेंज, सबसे ज़्यादा से लेकर सबसे कम तक इस क्रम में होती है: Fine, Coarse, और Blunt.

अगर एक से ज़्यादा पॉइंटिंग डिवाइस उपलब्ध हैं और उनकी सटीक जानकारी अलग-अलग है, तो पैरामीटर को सबसे सटीक जानकारी के साथ हल किया जाता है. उदाहरण के लिए, अगर दो पॉइंटिंग डिवाइस हैं — एक Fine सटीक डिवाइस और एक Blunt सटीक डिवाइस — तो Fine, pointerPrecision पैरामीटर की वैल्यू है.

नीचे दिए गए उदाहरण में, कम सटीक पॉइंटिंग डिवाइस का इस्तेमाल करने वाले उपयोगकर्ता को बड़ा बटन दिखाया गया है:

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

देखने की अनुमानित दूरी के हिसाब से यूज़र इंटरफ़ेस (यूआई) को अडजस्ट करना

देखने की दूरी, लेआउट तय करने में मदद करती है. अगर उपयोगकर्ता, ऐप्लिकेशन को दूर से इस्तेमाल कर रहा है, तो उसे टेक्स्ट और यूज़र इंटरफ़ेस (यूआई) एलिमेंट बड़े दिखने चाहिए. viewingDistance पैरामीटर, डिवाइस के टाइप और उसके सामान्य इस्तेमाल के हिसाब से, स्क्रीन से दूरी का अनुमान देता है.

UiMediaScope.ViewingDistance क्लास में तीन वैल्यू तय की गई हैं: Near, Medium, और Far. Near का मतलब है कि स्क्रीन पास है और Far का मतलब है कि डिवाइस को दूर से देखा जा रहा है. नीचे दिए गए उदाहरण में, स्क्रीन से दूरी Far या Medium होने पर, फ़ॉन्ट का साइज़ बढ़ जाता है:

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

यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट की झलक देखना

यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट की झलक देखने के लिए, कंपोज़ेबल फ़ंक्शन में 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 फ़ंक्शन के कॉन्टेंट लैम्डा में झलक देखने के लिए, कंपोज़ेबल को कॉल करें.

इस उदाहरण की मदद से, 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()
        }
    }
}