एक नज़र में जानकारी दिखाने वाला यूज़र इंटरफ़ेस (यूआई) बनाएं

इस पेज पर, साइज़ को मैनेज करने के तरीके के बारे में बताया गया है. साथ ही, ज़रूरत के हिसाब से और रिस्पॉन्सिव विज्ञापन बनाने का तरीका भी बताया गया है एक नज़र में जानकारी देने वाले मौजूदा कॉम्पोनेंट का इस्तेमाल करके, एक नज़र में जानकारी देने वाले लेआउट.

Box, Column, और Row का इस्तेमाल करें

एक नज़र में जानकारी देखने की सुविधा में तीन मुख्य कंपोज़ेबल लेआउट होते हैं:

  • Box: एलिमेंट को दूसरे के ऊपर रखा जाता है. इसका अनुवाद RelativeLayout होता है.

  • Column: वर्टिकल ऐक्सिस में एलिमेंट को एक-दूसरे के बाद रखा जाता है. यह अनुवाद करता है LinearLayout की वर्टिकल ओरिएंटेशन वाली इमेज.

  • Row: हॉरिज़ॉन्टल ऐक्सिस में एलिमेंट को एक-दूसरे के बाद रखा जाता है. यह अनुवाद करता है हॉरिज़ॉन्टल ओरिएंटेशन वाले LinearLayout पर सेट करें.

एक नज़र में जानकारी देखने की सुविधा, Scaffold ऑब्जेक्ट के साथ काम करती है. अपने Column, Row, और दिए गए Scaffold ऑब्जेक्ट में Box कंपोज़ेबल.

कॉलम, पंक्ति, और बॉक्स के लेआउट की इमेज.
पहली इमेज. कॉलम, पंक्ति, और बॉक्स वाले लेआउट के उदाहरण.

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

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

Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) {
    val modifier = GlanceModifier.defaultWeight()
    Text("first", modifier)
    Text("second", modifier)
    Text("third", modifier)
}

Row में, तय की गई ज़्यादा से ज़्यादा चौड़ाई का पता चलता है. ऐसा इसलिए है, क्योंकि हर बच्चे की चौड़ाई एक जैसी होती है तो वे सभी उपलब्ध स्थान को बराबर शेयर करते हैं. आपके पास अलग-अलग वज़न तय करने, लेआउट, पैडिंग (जगह) या अलाइनमेंट को अपनी ज़रूरत के हिसाब से बदल सकते हैं.

स्क्रोल किए जा सकने वाले लेआउट इस्तेमाल करें

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

नीचे दिए गए स्निपेट, LazyColumn.

आइटम की संख्या बताई जा सकती है:

// Remember to import Glance Composables
// import androidx.glance.appwidget.layout.LazyColumn

LazyColumn {
    items(10) { index: Int ->
        Text(
            text = "Item $index",
            modifier = GlanceModifier.fillMaxWidth()
        )
    }
}

अलग-अलग आइटम उपलब्ध कराएं:

LazyColumn {
    item {
        Text("First Item")
    }
    item {
        Text("Second Item")
    }
}

आइटम की सूची या कैटगरी दें:

LazyColumn {
    items(peopleNameList) { name ->
        Text(name)
    }
}

ऊपर दिए गए उदाहरणों के कॉम्बिनेशन का भी इस्तेमाल किया जा सकता है:

LazyColumn {
    item {
        Text("Names:")
    }
    items(peopleNameList) { name ->
        Text(name)
    }

    // or in case you need the index:
    itemsIndexed(peopleNameList) { index, person ->
        Text("$person at index $index")
    }
}

ध्यान दें कि पिछले स्निपेट में itemId की जानकारी नहीं है. itemId से, पेज की परफ़ॉर्मेंस को बेहतर बनाने और स्क्रोल करते रहने में मदद मिलती है Android 12 और उसके बाद के वर्शन के लिए, appWidget अपडेट और पूरी सूची की मदद से रैंक उदाहरण के लिए, सूची में से आइटम जोड़ते या हटाते समय). यह उदाहरण itemId के बारे में बताने का तरीका दिखाता है:

items(items = peopleList, key = { person -> person.id }) { person ->
    Text(person.name)
}

SizeMode तय करें

डिवाइस, उपयोगकर्ता की पसंद या लॉन्चर के हिसाब से, AppWidget के साइज़ अलग-अलग हो सकते हैं. इसलिए, आपके विज्ञापन के लिए उपलब्ध कराए गए विकल्पों के हिसाब से, सुविधाजनक विजेट लेआउट पेज. SizeMode की मदद से, एक नज़र में जानकारी देखने की सुविधा इसे आसान बना देती है परिभाषा और LocalSize मान. इन सेक्शन में, उन तीनों के बारे में बताया गया है मोड.

SizeMode.Single

डिफ़ॉल्ट मोड SizeMode.Single है. इससे यह पता चलता है कि कॉन्टेंट उपलब्ध कराया गया हो; इसका मतलब है कि AppWidget के उपलब्ध साइज़ में बदलाव होने पर भी, कॉन्टेंट का साइज़ बदला नहीं गया है.

class MyAppWidget : GlanceAppWidget() {

    override val sizeMode = SizeMode.Single

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // ...

        provideContent {
            MyContent()
        }
    }

    @Composable
    private fun MyContent() {
        // Size will be the minimum size or resizable
        // size defined in the App Widget metadata
        val size = LocalSize.current
        // ...
    }
}

इस मोड का इस्तेमाल करते समय, पक्का करें कि:

  • कम से कम और ज़्यादा से ज़्यादा साइज़ की मेटाडेटा वैल्यू, के हिसाब से व्यवस्थित किया जा सकता है.
  • कॉन्टेंट में ज़रूरत के हिसाब से साइज़ की रेंज होनी चाहिए.

आम तौर पर, आपको इस मोड का इस्तेमाल तब करना चाहिए, जब:

a) AppWidget का साइज़ तय हो या b) आकार बदलने पर यह अपनी सामग्री में बदलाव नहीं करता.

SizeMode.Responsive

यह मोड रिस्पॉन्सिव लेआउट उपलब्ध कराने के बराबर है, जिससे GlanceAppWidget की मदद से, खास साइज़. हर एक तय साइज़ के लिए, कॉन्टेंट बनाया जाता है और उसे खास AppWidget के बनने या अपडेट होने पर साइज़. इसके बाद, सिस्टम सबसे सही साइज़.

उदाहरण के लिए, हमारे डेस्टिनेशन AppWidget में, तीन साइज़ और उनके सामग्री:

class MyAppWidget : GlanceAppWidget() {

    companion object {
        private val SMALL_SQUARE = DpSize(100.dp, 100.dp)
        private val HORIZONTAL_RECTANGLE = DpSize(250.dp, 100.dp)
        private val BIG_SQUARE = DpSize(250.dp, 250.dp)
    }

    override val sizeMode = SizeMode.Responsive(
        setOf(
            SMALL_SQUARE,
            HORIZONTAL_RECTANGLE,
            BIG_SQUARE
        )
    )

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // ...

        provideContent {
            MyContent()
        }
    }

    @Composable
    private fun MyContent() {
        // Size will be one of the sizes defined above.
        val size = LocalSize.current
        Column {
            if (size.height >= BIG_SQUARE.height) {
                Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp))
            }
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Button()
                Button()
                if (size.width >= HORIZONTAL_RECTANGLE.width) {
                    Button("School")
                }
            }
            if (size.height >= BIG_SQUARE.height) {
                Text(text = "provided by X")
            }
        }
    }
}

पिछले उदाहरण में, provideContent तरीके को तीन बार कॉल किया गया है और तय साइज़ के हिसाब से मैप किया गया हो.

  • पहली कॉल में, साइज़ की वैल्यू 100x100 होगी. कॉन्टेंट ऐसा नहीं है अतिरिक्त बटन शामिल नहीं करना चाहिए, न ही ऊपर और नीचे के टेक्स्ट शामिल करने होंगे.
  • दूसरे कॉल में, साइज़ की वैल्यू 250x100 होगी. कॉन्टेंट में ये शामिल हैं अतिरिक्त बटन का इस्तेमाल किया जा सकता है, लेकिन टॉप और बॉटम टेक्स्ट नहीं.
  • तीसरे कॉल में, साइज़ का आकलन 250x250 में होगा. कॉन्टेंट में ये शामिल हैं अतिरिक्त बटन और दोनों टेक्स्ट के साथ काम करते हैं.

SizeMode.Responsive में अन्य दो मोड का कॉम्बिनेशन है. इसकी मदद से, आपको तय की गई सीमाओं में ही रिस्पॉन्सिव कॉन्टेंट को परिभाषित किया जा सकता है. आम तौर पर, यह मोड बेहतर परफ़ॉर्म करता है. साथ ही, AppWidget का साइज़ बदलने पर, ट्रांज़िशन को आसान बनाता है.

नीचे दी गई टेबल में, SizeMode और AppWidget का उपलब्ध साइज़:

साइज़ 105 x 110 203 x 112 72 x 72 203 x 150
SizeMode.Single 110 x 110 110 x 110 110 x 110 110 x 110
SizeMode.Exact 105 x 110 203 x 112 72 x 72 203 x 150
SizeMode.Responsive 80 x 100 80 x 100 80 x 100 150 x 120
* सटीक वैल्यू, सिर्फ़ डेमो के मकसद से दी गई हैं.

SizeMode.Exact

SizeMode.Exact, एग्ज़ैक्ट लेआउट उपलब्ध कराने के बराबर है, जो AppWidget के उपलब्ध साइज़ के हिसाब से, हर बार GlanceAppWidget कॉन्टेंट का अनुरोध किया जाता है बदलाव (उदाहरण के लिए, जब उपयोगकर्ता होमस्क्रीन में AppWidget का साइज़ बदलता है).

उदाहरण के लिए, गंतव्य विजेट में, एक अतिरिक्त बटन जोड़ा जा सकता है, अगर उपलब्ध चौड़ाई किसी तय वैल्यू से ज़्यादा है.

class MyAppWidget : GlanceAppWidget() {

    override val sizeMode = SizeMode.Exact

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // ...

        provideContent {
            MyContent()
        }
    }

    @Composable
    private fun MyContent() {
        // Size will be the size of the AppWidget
        val size = LocalSize.current
        Column {
            Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp))
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Button()
                Button()
                if (size.width > 250.dp) {
                    Button("School")
                }
            }
        }
    }
}

यह मोड, अन्य मोड के मुकाबले ज़्यादा सुविधा देता है. हालांकि, इसमें कुछ सुविधाएं होती हैं सावधानियां:

  • हर बार साइज़ बदलने पर, AppWidget को पूरी तरह से फिर से बनाना होगा. यह कॉन्टेंट की परफ़ॉर्मेंस मुश्किल होने पर, यूज़र इंटरफ़ेस (यूआई) जंप हो सकता है.
  • उपलब्ध साइज़, लॉन्चर लागू करने के तरीके के हिसाब से अलग-अलग हो सकता है. उदाहरण के लिए, यदि लॉन्चर आकार की सूची उपलब्ध नहीं कराता, तो कम से कम संभावित साइज़ का इस्तेमाल किया गया है.
  • Android 12 से पहले के वर्शन वाले डिवाइसों में, हो सकता है कि साइज़ का हिसाब लगाने वाला लॉजिक सभी डिवाइसों में काम न करे स्थितियों के बारे में बताना.

आम तौर पर, अगर SizeMode.Responsive का इस्तेमाल नहीं किया जा सकता, तो आपको इस मोड का इस्तेमाल करना चाहिए (इसका मतलब है कि रिस्पॉन्सिव लेआउट का एक छोटा सेट काम नहीं करता है).

संसाधन ऐक्सेस करें

Android के किसी भी संसाधन को ऐक्सेस करने के लिए, LocalContext.current का इस्तेमाल करें. इसके बारे में यहां बताया गया है नीचे दिया गया उदाहरण:

LocalContext.current.getString(R.string.glance_title)

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

कंपोज़ेबल और मेथड, "provider" का इस्तेमाल करके रिसॉर्स को स्वीकार करते हैं, जैसे ImageProvider या ओवरलोड का इस्तेमाल करें, जैसे कि GlanceModifier.background(R.color.blue). उदाहरण के लिए:

Column(
    modifier = GlanceModifier.background(R.color.default_widget_background)
) { /**...*/ }

Image(
    provider = ImageProvider(R.drawable.ic_logo),
    contentDescription = "My image",
)

टेक्स्ट हैंडल करना

एक नज़र में जानकारी 1.1.0 में आपके टेक्स्ट के स्टाइल सेट करने के लिए एक एपीआई शामिल है. इसका उपयोग करके टेक्स्ट शैलियां सेट करें TextStyle क्लास के fontSize, fontWeight या fontFamily एट्रिब्यूट.

fontFamily में सभी सिस्टम फ़ॉन्ट इस्तेमाल किए जा सकते हैं, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है, लेकिन ऐप्लिकेशन में कस्टम फ़ॉन्ट काम नहीं करते:

Text(
    style = TextStyle(
        fontWeight = FontWeight.Bold,
        fontSize = 18.sp,
        fontFamily = FontFamily.Monospace
    ),
    text = "Example Text"
)

कंपाउंड बटन जोड़ना

कंपाउंड बटन की सुविधा Android 12 में शुरू की गई थी. एक नज़र में जानकारी देखने की सुविधा, पीछे की ओर काम करती है इस तरह के कंपाउंड बटन के साथ काम करता है:

ये कंपाउंड बटन, हर एक क्लिक करने लायक व्यू दिखाते हैं जो "चुना गया" state.

var isApplesChecked by remember { mutableStateOf(false) }
var isEnabledSwitched by remember { mutableStateOf(false) }
var isRadioChecked by remember { mutableStateOf(0) }

CheckBox(
    checked = isApplesChecked,
    onCheckedChange = { isApplesChecked = !isApplesChecked },
    text = "Apples"
)

Switch(
    checked = isEnabledSwitched,
    onCheckedChange = { isEnabledSwitched = !isEnabledSwitched },
    text = "Enabled"
)

RadioButton(
    checked = isRadioChecked == 1,
    onClick = { isRadioChecked = 1 },
    text = "Checked"
)

इस स्थिति में बदलाव होने पर, दिया गया लैम्डा ट्रिगर हो जाता है. आप सही का निशान लगाएं, जैसा कि इस उदाहरण में दिखाया गया है:

class MyAppWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        val myRepository = MyRepository.getInstance()

        provideContent {
            val scope = rememberCoroutineScope()

            val saveApple: (Boolean) -> Unit =
                { scope.launch { myRepository.saveApple(it) } }
            MyContent(saveApple)
        }
    }

    @Composable
    private fun MyContent(saveApple: (Boolean) -> Unit) {

        var isAppleChecked by remember { mutableStateOf(false) }

        Button(
            text = "Save",
            onClick = { saveApple(isAppleChecked) }
        )
    }
}

आप colors एट्रिब्यूट को CheckBox, Switch, और RadioButton की मदद से रंगों को पसंद के मुताबिक बनाएं:

CheckBox(
    // ...
    colors = CheckboxDefaults.colors(
        checkedColor = ColorProvider(day = colorAccentDay, night = colorAccentNight),
        uncheckedColor = ColorProvider(day = Color.DarkGray, night = Color.LightGray)
    ),
    checked = isChecked,
    onCheckedChange = { isChecked = !isChecked }
)

Switch(
    // ...
    colors = SwitchDefaults.colors(
        checkedThumbColor = ColorProvider(day = Color.Red, night = Color.Cyan),
        uncheckedThumbColor = ColorProvider(day = Color.Green, night = Color.Magenta),
        checkedTrackColor = ColorProvider(day = Color.Blue, night = Color.Yellow),
        uncheckedTrackColor = ColorProvider(day = Color.Magenta, night = Color.Green)
    ),
    checked = isChecked,
    onCheckedChange = { isChecked = !isChecked },
    text = "Enabled"
)

RadioButton(
    // ...
    colors = RadioButtonDefaults.colors(
        checkedColor = ColorProvider(day = Color.Cyan, night = Color.Yellow),
        uncheckedColor = ColorProvider(day = Color.Red, night = Color.Blue)
    ),

)

अतिरिक्त कॉम्पोनेंट

एक नज़र में जानकारी 1.1.0 में, अतिरिक्त कॉम्पोनेंट रिलीज़ करना शामिल है, जैसा कि निम्न तालिका:

नाम इमेज रेफ़रंस लिंक अतिरिक्त नोट
फ़िल्ड बटन alt_text कॉम्पोनेंट
आउटलाइन बटन alt_text कॉम्पोनेंट
आइकॉन बटन alt_text कॉम्पोनेंट प्राइमरी / सेकंडरी / सिर्फ़ आइकॉन
टाइटल बार alt_text कॉम्पोनेंट
स्कैफ़ोल्ड स्कैफ़ोल्ड और टाइटल बार एक ही डेमो में हैं.

डिज़ाइन की विशेषताओं के बारे में ज़्यादा जानकारी के लिए, इसमें कॉम्पोनेंट के डिज़ाइन देखें Figma पर डिज़ाइन किट उपलब्ध है.