Bu sayfada, mevcut Glance bileşenlerini kullanarak Glance ile boyutları nasıl yöneteceğiniz ve esnek ve duyarlı düzenler nasıl sağlayacağınız açıklanmaktadır.
Box
, Column
ve Row
özelliğini kullanın
Bir bakışta üç temel birleştirilebilir düzen vardır:
Box
: Öğeleri birbirinin üzerine yerleştirir. Bu,RelativeLayout
olarak çevrilir.Column
: Öğeleri dikey eksende birbirinin üzerine yerleştirir. Bu, dikey yöne sahip birLinearLayout
olarak çevrilir.Row
: Öğeleri yatay eksende birbirinin arkasına yerleştirir. Yatay yönde birLinearLayout
olarak çevrilir.
Bir Bakışta, Scaffold
nesnelerini destekler. Column
, Row
ve Box
bileşenlerinizi belirli bir Scaffold
nesnesine yerleştirin.
Bu bileşenlerin her biri, içeriklerinin dikey ve yatay hizalamalarını ve genişlik, yükseklik, ağırlık veya dolgu kısıtlamalarını değiştiricileri kullanarak tanımlamanıza olanak tanır. Ayrıca her alt öğe, ebeveyn öğe içindeki alanı ve yerleşimi değiştirmek için kendi değiştiricisini tanımlayabilir.
Aşağıdaki örnekte, alt öğelerini yatay olarak eşit şekilde dağıtan bir Row
öğesinin nasıl oluşturulacağı gösterilmektedir (Şekil 1):
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
, mevcut maksimum genişliği doldurur ve her çocuğun ağırlığı aynı olduğundan, kullanılabilir alanı eşit olarak paylaşırlar. Düzenleri ihtiyaçlarınıza uyarlamak için farklı ağırlıklar, boyutlar, dolgular veya hizalamalar tanımlayabilirsiniz.
Kaydırılabilir düzenler kullanma
Duyarlı içerik sunmanın bir diğer yolu da içeriği kaydırılabilir hâle getirmektir. Bu, LazyColumn
bileşeni ile mümkündür. Bu bileşen, uygulama widget'ında kaydırılabilir bir kapsayıcı içinde görüntülenecek bir öğe grubu tanımlamanıza olanak tanır.
Aşağıdaki snippet'lerde, LazyColumn
içindeki öğeleri tanımlamanın farklı yolları gösterilmektedir.
Öğe sayısını belirtebilirsiniz:
// Remember to import Glance Composables // import androidx.glance.appwidget.layout.LazyColumn LazyColumn { items(10) { index: Int -> Text( text = "Item $index", modifier = GlanceModifier.fillMaxWidth() ) } }
Öğeleri tek tek sağlayın:
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
Bir öğe listesi veya dizisi sağlayın:
LazyColumn { items(peopleNameList) { name -> Text(name) } }
Önceki örneklerin bir kombinasyonunu da kullanabilirsiniz:
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") } }
Önceki snippet'te itemId
belirtilmediğini unutmayın. itemId
belirtmek, Android 12 ve sonraki sürümlerde liste ve appWidget
güncellemeleri sırasında performansı iyileştirmeye ve kaydırma konumunu korumaya yardımcı olur (örneğin, listede öğe eklerken veya listeden öğe çıkarırken). Aşağıdaki örnekte, itemId
değerinin nasıl belirtileceği gösterilmektedir:
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
değerini tanımlayın
AppWidget
boyutları cihaza, kullanıcı seçimine veya başlatıcıya bağlı olarak farklılık gösterebilir. Bu nedenle, Esnek widget düzenleri sağlama sayfasında açıklandığı gibi esnek düzenler sağlamanız önemlidir. Bir Bakışta, SizeMode
tanımı ve LocalSize
değeriyle bunu basitleştirir. Aşağıdaki bölümlerde üç mod açıklanmaktadır.
SizeMode.Single
SizeMode.Single
varsayılan moddur. Yalnızca bir tür içerik sağlandığını gösterir. Yani, AppWidget
kullanılabilir boyutu değişse bile içerik boyutu değişmez.
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 // ... } }
Bu modu kullanırken aşağıdakilerden emin olun:
- Minimum ve maksimum boyut meta veri değerleri, içerik boyutuna göre doğru şekilde tanımlanmalıdır.
- İçerik, beklenen boyut aralığında yeterince esnektir.
Genel olarak bu modu şu durumlarda kullanmalısınız:
a) AppWidget
sabit boyuttadır veya b) yeniden boyutlandırıldığında içeriği değişmez.
SizeMode.Responsive
Bu mod, GlanceAppWidget
'nin belirli boyutlarla sınırlı bir dizi duyarlı düzen tanımlamasına olanak tanıyan duyarlı düzenler sağlama ile aynıdır. Tanımlanmış her boyut için içerik oluşturulur ve AppWidget
oluşturulduğunda veya güncellendiğinde belirli boyutla eşlenir. Ardından sistem, mevcut boyuta göre en uygun olanı seçer.
Örneğin, hedefimiz AppWidget
'te üç boyut ve içeriğini tanımlayabilirsiniz:
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") } } } }
Önceki örnekte provideContent
yöntemi üç kez çağrılır ve tanımlanan boyutla eşlenir.
- İlk çağrıda boyut
100x100
olarak değerlendirilir. İçerikte ek düğme, üst ve alt metinler yer almıyor. - İkinci çağrıda boyut
250x100
olarak değerlendirilir. İçerikte ek düğme yer alıyor ancak üst ve alt metinler yer almıyor. - Üçüncü çağrıda boyut
250x250
olarak değerlendirilir. İçerikte ek düğme ve her iki metin de yer alır.
SizeMode.Responsive
, diğer iki modun bir kombinasyonudur ve önceden tanımlanmış sınırlar içinde duyarlı içerik tanımlamanıza olanak tanır. Genel olarak bu mod daha iyi performans gösterir ve AppWidget
yeniden boyutlandırıldığında daha yumuşak geçişler sağlar.
Aşağıdaki tabloda, SizeMode
ve AppWidget
kullanılabilir boyutuna bağlı olarak boyutun değeri gösterilmektedir:
Kullanılabilir boyut | 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 |
* Tam değerler yalnızca demo amaçlıdır. |
SizeMode.Exact
SizeMode.Exact
, tam sayfa düzenleri sağlamanın eşdeğeridir. Bu durumda, mevcut AppWidget
boyutu her değiştiğinde (ör. kullanıcı ana ekrandaki AppWidget
'i yeniden boyutlandırdığında) GlanceAppWidget
içeriği istenir.
Örneğin, mevcut genişlik belirli bir değerden büyükse hedef widget'a ek bir düğme eklenebilir.
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") } } } } }
Bu mod diğerlerinden daha fazla esneklik sağlar ancak bazı dezavantajları vardır:
AppWidget
, boyut her değiştiğinde tamamen yeniden oluşturulmalıdır. Bu, içerik karmaşık olduğunda performans sorunlarına ve kullanıcı arayüzünde atlamalara neden olabilir.- Kullanılabilir boyut, başlatıcının uygulanmasına bağlı olarak farklılık gösterebilir. Örneğin, başlatıcı boyut listesini sağlamazsa mümkün olan minimum boyut kullanılır.
- Android 12 öncesi cihazlarda boyut hesaplama mantığı her durumda çalışmayabilir.
Genel olarak, SizeMode.Responsive
kullanılamıyorsa (yani küçük bir duyarlı düzen grubu uygun değilse) bu modu kullanmanız gerekir.
Kaynaklara erişim
Aşağıdaki örnekte gösterildiği gibi, herhangi bir Android kaynağına erişmek için LocalContext.current
kullanın:
LocalContext.current.getString(R.string.glance_title)
Nihai RemoteViews
nesnesinin boyutunu azaltmak ve dinamik renkler gibi dinamik kaynakları etkinleştirmek için doğrudan kaynak kimlikleri sağlamanızı öneririz.
Birleştirilebilirler ve yöntemler, ImageProvider
gibi bir "sağlayıcı" kullanarak veya GlanceModifier.background(R.color.blue)
gibi bir aşırı yükleme yöntemi kullanarak kaynakları kabul eder. Örnek:
Column( modifier = GlanceModifier.background(R.color.default_widget_background) ) { /**...*/ } Image( provider = ImageProvider(R.drawable.ic_logo), contentDescription = "My image", )
Herkese açık kullanıcı adı metni
Glance 1.1.0, metin stillerinizi ayarlamak için bir API içerir. TextStyle sınıfının fontSize
, fontWeight
veya fontFamily
özelliklerini kullanarak metin stillerini ayarlayın.
fontFamily
, aşağıdaki örnekte gösterildiği gibi tüm sistem yazı tiplerini destekler ancak uygulamalardaki özel yazı tipleri desteklenmez:
Text(
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
),
text = "Example Text"
)
Karmaşık düğmeler ekleme
Karma düğmeler Android 12'de kullanıma sunulmuştur. Glance, aşağıdaki karma düğme türleri için geriye dönük uyumluluğu destekler:
Bu birleşik düğmelerin her biri, "işaretli" durumu gösteren tıklanabilir bir görünüm gösterir.
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" )
Durum değiştiğinde sağlanan lambda tetiklenir. Kontrol durumunu aşağıdaki örnekte gösterildiği gibi saklayabilirsiniz:
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) } ) } }
Renklerini özelleştirmek için CheckBox
, Switch
ve RadioButton
için colors
özelliğini de sağlayabilirsiniz:
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) ), )
Ek bileşenler
Glance 1.1.0, aşağıdaki tabloda açıklandığı gibi ek bileşenlerin yayınlanmasını içerir:
Ad | Resim | Referans bağlantısı | Ek notlar |
---|---|---|---|
Doldurulmuş düğme | Bileşen | ||
Dış Çizgili Düğmeler | Bileşen | ||
Simge düğmeleri | Bileşen | Birincil / İkincil / Yalnızca simge | |
Başlık çubuğu | Bileşen | ||
İskele | İskelet ve başlık çubuğu aynı demodadır. |
Tasarım ayrıntıları hakkında daha fazla bilgi için Figma'daki bu tasarım kitindeki bileşen tasarımlarına bakın.
Standart düzenler hakkında daha fazla bilgi için Standart widget düzenleri başlıklı makaleyi inceleyin.