Wear OS के लिए, Compose में मौजूद सूचियां


Wear OS डिवाइसों पर, सूचियों की मदद से उपयोगकर्ता विकल्पों के सेट में से कोई आइटम चुन सकते हैं.

Wear OS वाले कई डिवाइसों में गोल स्क्रीन होती हैं. इस वजह से, स्क्रीन के सबसे ऊपर और सबसे नीचे दिखने वाले आइटम को देखना मुश्किल हो जाता है. इस वजह से, Compose for Wear OS में LazyColumn क्लास का एक वर्शन शामिल है, जिसे TransformingLazyColumn कहा जाता है. यह स्केलिंग और मॉर्फ़िंग ऐनिमेशन के साथ काम करता है. जब आइटम किनारों की ओर जाते हैं, तो वे छोटे हो जाते हैं और धुंधले हो जाते हैं.

सुझाए गए स्केलिंग और स्क्रोलिंग इफ़ेक्ट लागू करने के लिए:

  1. Modifier.transformedHeight का इस्तेमाल करें, ताकि कंपोज़र को स्क्रीन पर आइटम स्क्रोल होने पर ऊंचाई में हुए बदलाव का हिसाब लगाने की अनुमति मिल सके.
  2. आइटम के कॉन्टेंट को छोटा करने के साथ-साथ, विज़ुअल इफ़ेक्ट लागू करने के लिए transformation = SurfaceTransformation(transformationSpec) का इस्तेमाल करें.
  3. उन कॉम्पोनेंट के लिए कस्टम TransformationSpec का इस्तेमाल करें जो transformation को पैरामीटर के तौर पर नहीं लेते. जैसे, Text.

इस एनिमेशन में दिखाया गया है कि स्क्रीन के सबसे ऊपर और सबसे नीचे पहुंचने पर, सूची का एलिमेंट कैसे स्केल होता है और उसका आकार कैसे बदलता है:

यहां दिए गए कोड स्निपेट में, TransformingLazyColumn लेआउट का इस्तेमाल करके सूची बनाने का तरीका बताया गया है. इससे ऐसा कॉन्टेंट बनाया जा सकता है जो Wear OS की अलग-अलग स्क्रीन साइज़ पर शानदार दिखता है.

स्निपेट में minimumVerticalContentPadding मॉडिफ़ायर के इस्तेमाल के बारे में भी बताया गया है. आपको सूची के आइटम पर इसे सेट करना चाहिए, ताकि सूची के ऊपर और नीचे सही पैडिंग लागू की जा सके.

स्क्रोल इंडिकेटर दिखाने के लिए, ScreenScaffold और TransformingLazyColumn के बीच columnState शेयर करें:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

स्नैप-एंड-फ़्लिंग इफ़ेक्ट जोड़ना

स्नैपिंग की सुविधा यह पक्का करती है कि जब कोई उपयोगकर्ता स्क्रोल या फ़्लिंग जेस्चर पूरा कर लेता है, तो सूची में मौजूद कोई आइटम, स्क्रीन के किसी खास पॉइंट पर सटीक तरीके से सेट हो जाए. आम तौर पर, यह पॉइंट स्क्रीन का बीच वाला हिस्सा होता है. गोल स्क्रीन पर, आइटम बीच से दूर जाने पर छोटे होते जाते हैं और उनकी बनावट बदलती जाती है. ऐसे में, स्नैपिंग की सुविधा खास तौर पर काम आती है. इससे यह पक्का किया जा सकता है कि सबसे काम का आइटम, देखने के लिए सबसे सही जगह पर पूरी तरह से दिखे और पढ़ा जा सके.

स्नैप-एंड-फ़्लिंग की सुविधा जोड़ने के लिए, flingBehavior पैरामीटर को TransformingLazyColumnDefaults.snapFlingBehavior(columnState) पर सेट करें. फ़िज़िकल क्राउन या बेज़ल का इस्तेमाल करते समय, एक जैसा अनुभव पाने के लिए RotaryScrollableDefaults.snapBehavior(columnState) का इस्तेमाल करके, rotaryScrollableBehavior को मैच पर सेट करें.

val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(scrollState = columnState) {
    TransformingLazyColumn(
        state = columnState,
        flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
        rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
    ) {
        // ...
        // ...
    }
}

उल्टा लेआउट

डिफ़ॉल्ट रूप से, स्क्रोल की जा सकने वाली सूची, अपने सबसे ऊपरी किनारे पर ऐंकर होती है. अगर कोई उपयोगकर्ता किसी स्टैंडर्ड सूची के सबसे नीचे तक स्क्रोल करता है और सूची के आखिर में कोई नया आइटम जोड़ा जाता है, तो सूची में उपयोगकर्ता को मौजूदा आइटम दिखता रहता है. उदाहरण के लिए, अगर उपयोगकर्ता स्क्रीन पर सबसे नीचे मौजूद आइटम 10 को देख रहा है और आइटम 11 को जोड़ दिया जाता है, तो व्यू आइटम 10 पर ही फ़ोकस रहेगा. साथ ही, आइटम 11, मौजूदा व्यू के नीचे स्क्रीन से बाहर दिखेगा.

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

इन इस्तेमाल के उदाहरणों के लिए, TransformingLazyColumn आपको reverseLayout = true सेट करके लेआउट को उलटने की सुविधा देता है. इससे सूची का ऐंकर, सबसे ऊपर वाले किनारे से बदलकर सबसे नीचे वाला किनारा हो जाता है.

आसानी के लिए, reverseLayout = true को सेट करने पर, आइटम का विज़ुअल क्रम और स्क्रोल करने के जेस्चर की दिशा भी उलट जाती है:

  • आइटम को नीचे से ऊपर की ओर रखा जाता है. इसका मतलब है कि इंडेक्स 0 वाला आइटम, स्क्रीन पर सबसे नीचे दिखता है.
  • ऊपर की ओर स्क्रोल करने पर, ज़्यादा इंडेक्स वाले आइटम दिखते हैं.

स्नैप-एंड-फ़्लिंग के साथ-साथ रिवर्स लेआउट जोड़ने के लिए, flingBehavior और rotaryScrollableBehavior को एक साथ इस्तेमाल किया जा सकता है. इसके लिए, यहां दिया गया स्निपेट देखें:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding,
        reverseLayout = true,
        modifier = Modifier.fillMaxWidth()
    ) {
        items(10) { index ->
            Button(
                label = {
                    Text(
                        text = "Item ${index + 1}"
                    )
                },
                onClick = {},
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            )
        }
        item {
            // With reverseLayout = true, the last item declared appears at the top.
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text("Header")
            }
        }
    }
}

यहां दी गई इमेज में, सामान्य सूची और उल्टी सूची के बीच का अंतर दिखाया गया है:

सामान्य लेआउट वाला TransformingLazyColumn, जिसमें आइटम 1 सबसे ऊपर और आइटम बढ़ते क्रम में दिख रहे हैं.
पहली इमेज. यह एक स्टैंडर्ड लिस्ट लेआउट है, जिसमें कॉन्टेंट ऊपर से नीचे तक दिखता है.
रिवर्स लेआउट वाला TransformingLazyColumn, जिसमें आइटम 1 सबसे नीचे और बाकी आइटम ऊपर की ओर घटते क्रम में दिख रहे हैं.
दूसरी इमेज. उल्टी सूची वाला लेआउट, जिसमें कॉन्टेंट नीचे से ऊपर की ओर दिखता है.