इस पेज में, Glance के मौजूदा कॉम्पोनेंट का इस्तेमाल करके, Glance के लेआउट के साइज़ को मैनेज करने और उन्हें ज़रूरत के मुताबिक बनाने का तरीका बताया गया है.
Box
, Column
, और Row
का इस्तेमाल करें
Glance में तीन मुख्य कॉम्पोज़ेबल लेआउट होते हैं:
Box
: एलिमेंट को एक-दूसरे के ऊपर रखता है. इसका अनुवादRelativeLayout
में किया जाता है.Column
: वर्टिकल ऐक्सिस में, एलिमेंट को एक-दूसरे के बाद रखता है. यह वर्टिकल ओरिएंटेशन वालेLinearLayout
में बदल जाता है.Row
: यह हॉरिज़ॉन्टल ऐक्सिस में, एलिमेंट को एक-दूसरे के बाद रखता है. यह हॉरिज़ॉन्टल ओरिएंटेशन वालेLinearLayout
में बदल जाता है.
एक नज़र में जानकारी देखने की सुविधा, Scaffold
ऑब्जेक्ट के साथ काम करती है. अपने Column
, Row
, और
Box
कॉम्पोज़ेबल को किसी दिए गए Scaffold
ऑब्जेक्ट में डालें.
इनमें से हर कॉम्पोनस की मदद से, कॉन्टेंट के वर्टिकल और हॉरिज़ॉन्टल अलाइनमेंट के साथ-साथ, चौड़ाई, ऊंचाई, वज़न या पैडिंग की सीमाएं तय की जा सकती हैं. इसके लिए, आपको मॉडिफ़ायर का इस्तेमाल करना होगा. इसके अलावा, हर बच्चा अपने मॉडिफ़ायर तय कर सकता है, ताकि पैरंट में स्पेस और प्लेसमेंट बदला जा सके.
नीचे दिए गए उदाहरण में, Row
बनाने का तरीका बताया गया है. इसमें, इसके चाइल्ड एलिमेंट को हॉरिज़ॉन्टल तौर पर बराबर-बराबर बांटा गया है, जैसा कि पहले चित्र में दिखाया गया है:
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
, सही लेआउट उपलब्ध कराने के बराबर है. यह हर बार GlanceAppWidget
कॉन्टेंट का अनुरोध करता है, जब उपलब्ध AppWidget
का साइज़ बदलता है. उदाहरण के लिए, जब उपयोगकर्ता होमस्क्रीन में 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
ऑब्जेक्ट का साइज़ कम करने और डाइनैमिक रंग जैसे डाइनैमिक संसाधनों को चालू करने के लिए, सीधे तौर पर संसाधन आईडी दें.
कॉम्पोज़ेबल और तरीके, 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", )
टेक्स्ट को हैंडल करना
Glance 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 में लॉन्च किए गए थे. Glance, इस तरह के कंपाउंड बटन के साथ काम करता है:
इन कंपाउंड बटन में से हर बटन पर क्लिक किया जा सकता है. यह बटन, "चुनी गई" स्थिति दिखाता है.
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) } ) } }
CheckBox
, Switch
, और
RadioButton
के रंगों को पसंद के मुताबिक बनाने के लिए, उनके लिए colors
एट्रिब्यूट की वैल्यू भी सबमिट की जा सकती है:
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) ), )
अन्य कॉम्पोनेंट
Glance 1.1.0 में अन्य कॉम्पोनेंट भी रिलीज़ किए गए हैं. इनके बारे में नीचे दी गई टेबल में बताया गया है:
नाम | इमेज | रेफ़रंस लिंक | अतिरिक्त नोट |
---|---|---|---|
भरा हुआ बटन | कॉम्पोनेंट | ||
आउटलाइन वाले बटन | कॉम्पोनेंट | ||
आइकॉन बटन | कॉम्पोनेंट | प्राइमरी / सेकंडरी / सिर्फ़ आइकॉन | |
टाइटल बार | कॉम्पोनेंट | ||
मचान | स्कैफ़ोल्ड और टाइटल बार, एक ही डेमो में हैं. |
डिज़ाइन की खास बातों के बारे में ज़्यादा जानने के लिए, Figma पर इस डिज़ाइन किट में कॉम्पोनेंट के डिज़ाइन देखें.
कैननिकल लेआउट के बारे में ज़्यादा जानने के लिए, कैननिकल विजेट लेआउट पर जाएं.