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 lambda का आकलन करता है और बूलियन वैल्यू दिखाता है. उदाहरण के लिए, यहां दिया गया स्निपेट, 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()
}

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

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

pointerPrecision पैरामीटर से, उपलब्ध पॉइंटिंग डिवाइसों की सटीक जानकारी मिलती है. जैसे, माउस और टचस्क्रीन. UiMediaScope.PointerPrecision क्लास में चार वैल्यू तय की गई हैं: Fine, Coarse, Blunt, और None. None का मतलब है कि कोई पॉइंटिंग डिवाइस उपलब्ध नहीं है. सटीकता के हिसाब से, इन प्रॉपर्टी को इस क्रम में रखा गया है: 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()
    }
}

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

देखने की दूरी एक ऐसा फ़ैक्टर है जिससे लेआउट तय करने में मदद मिलती है. अगर उपयोगकर्ता दूर से ऐप्लिकेशन का इस्तेमाल कर रहा है, तो वह चाहेगा कि टेक्स्ट और यूज़र इंटरफ़ेस (यूआई) एलिमेंट बड़े हों. 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()
        }
    }
}