Bu sayfada, Glance ile boyutların nasıl ele alınacağı, esnek ve duyarlı düzenlerin nasıl sağlanacağı açıklanmaktadır.
Box
, Column
ve Row
kullanın
Glance'ta üç ana composable düzen vardır:
Box
: Öğeleri diğerlerinin üzerine yerleştirir.RelativeLayout
diline çevrilir.Column
: Öğeleri dikey eksene birbirinin ardından yerleştirir. Dikey yönlüLinearLayout
çevirir.Row
: Öğeleri yatay eksene birbirinin ardından yerleştirir. Yatay yönlü birLinearLayout
anlamına gelir.
Bu composable'ların her biri, içeriğinin dikey ve yatay hizalamasını ve genişlik, yükseklik, ağırlık veya dolgu kısıtlamalarını düzenleyiciler kullanarak tanımlamanıza olanak tanır. Buna ek olarak, her alt öğe, üst öğenin içindeki alanı ve yerleşimi değiştirmek için değiştiricisini tanımlayabilir.
Aşağıdaki örnekte, Şekil 1'de gösterildiği gibi alt öğelerini yatay olarak eşit şekilde dağıtan bir Row
öğesinin nasıl oluşturulacağı gösterilmektedir:
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
, kullanılabilir maksimum genişliği doldurur ve her alt öğe aynı ağırlığa sahip olduğu için kullanılabilir alanı eşit olarak paylaşır. Düzenleri ihtiyaçlarınıza göre uyarlamak için farklı ağırlıklar, boyutlar, dolgular veya hizalamalar tanımlayabilirsiniz.
Kaydırılabilir düzenler kullan
Duyarlı içerik sağlamanın bir başka yolu da kaydırılabilir hale getirmektir. Bunu LazyColumn
composable ile yapabilirsiniz. Bu composable, uygulama widget'ında kaydırılabilir bir kapsayıcı içinde görüntülenecek bir dizi öğe tanımlamanızı sağlar.
Aşağıdaki snippet'lerde LazyColumn
içindeki öğeleri tanımlamanın farklı yolları gösterilmektedir.
Öğe sayısını sağlayabilirsiniz:
// 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) } }
Yukarıdaki ö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'in itemId
belirtmediğini unutmayın. itemId
belirtilmesi, performansı iyileştirmeye ve Android 12'den sonraki appWidget
güncellemelerinin yanı sıra kaydırma konumunun korunmasına yardımcı olur (örneğin, listeye öğe eklerken veya listeden öğe kaldırırken). Aşağıdaki örnekte, bir itemId
öğesinin nasıl belirtileceği gösterilmektedir:
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
tanımlayın
AppWidget
boyutları cihaza, kullanıcı seçimine veya başlatıcıya bağlı olarak değişebilir. Bu nedenle, Esnek widget düzenleri sağlama sayfasında açıklandığı gibi esnek düzenler sağlamak önemlidir. Glance, SizeMode
tanımı ve LocalSize
değeri ile bunu basitleştirir. Aşağıdaki bölümlerde üç mod açıklanmaktadır.
SizeMode.Single
SizeMode.Single
varsayılan moddur. Yalnızca tek bir içerik türünün sağlandığını, yani AppWidget
kullanılabilir boyut değişse bile içerik boyutunun değişmediğini gösterir.
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 şunlardan emin olun:
- Minimum ve maksimum boyut meta veri değerleri, içerik boyutuna göre doğru şekilde tanımlanır.
- İçerik, beklenen boyut aralığında yeterince esnektir.
Genel olarak bu modu, aşağıdaki durumlardan herhangi biri geçerli olduğunda kullanmalısınız:
a) AppWidget
sabit bir boyuta sahipse veya
b) yeniden boyutlandırıldığında içeriğini değiştirmiyor.
SizeMode.Responsive
Bu mod, GlanceAppWidget
öğesinin belirli boyutlarla sınırlanmış bir duyarlı düzen grubu tanımlamasına olanak tanıyan duyarlı düzenler sağlama ile eşdeğerdir. Tanımlanan her boyut için içerik oluşturulur ve AppWidget
oluşturulurken veya güncellendiğinde belirli boyutla eşlenir. Daha sonra sistem, mevcut boyuta göre en uygun modeli seçer.
Örneğin, AppWidget
hedefimizde üç 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 boyuta eşlenir.
- İlk çağrıda boyut
100x100
olarak değerlendirilir. İçerikte ekstra düğme veya üst ve alt metinler yok. - İkinci çağrıda boyut
250x100
olarak değerlendirilir. İçerik ekstra düğme içeriyor, ancak üst ve alt metinleri içermiyor. - Üçüncü çağrıda boyut
250x250
olarak değerlendirilir. İçerikte "ekstra" düğmesi ve her iki metin de var.
SizeMode.Responsive
, diğer iki modun birleşimidir ve önceden tanımlanmış sınırlar içinde duyarlı içeriği tanımlamanıza olanak tanır. Genel olarak bu mod, AppWidget
yeniden boyutlandırıldığında daha iyi performans gösterir ve daha yumuşak geçişlere olanak tanır.
Aşağıdaki tabloda, SizeMode
ve kullanılabilir AppWidget
boyutuna bağlı olarak beden 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 |
* Kesin değerler yalnızca demo amaçlıdır. |
SizeMode.Exact
SizeMode.Exact
, kullanılabilir AppWidget
boyutu her değiştiğinde (örneğin, kullanıcı ana ekranda AppWidget
öğesini yeniden boyutlandırdığında) GlanceAppWidget
içeriğini isteyen tam düzenler sağlama ile eşdeğerdir.
Örneğin, kullanılabilir genişlik belirli bir değerden büyükse hedef widget'ta fazladan 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 dikkat edilmesi gereken birkaç nokta vardır:
- Boyut her değiştiğinde
AppWidget
tamamen yeniden oluşturulmalıdır. Bu durum, 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 uygulamasına bağlı olarak değişebilir. Örneğin, başlatıcı boyut listesini sağlamazsa olası minimum boyut kullanılır.
- Android 12 sürümünden önceki cihazlarda boyut hesaplama mantığı tüm durumlarda çalışmayabilir.
Genel olarak, SizeMode.Responsive
kullanılamıyorsa (yani duyarlı düzenlerden oluşan küçük bir grup uygun değilse) kullanmalısınız.
Kaynaklara erişin
Aşağıdaki örnekte gösterildiği gibi, herhangi bir Android kaynağına erişmek için LocalContext.current
öğesini kullanın:
LocalContext.current.getString(R.string.glance_title)
Son RemoteViews
nesnesinin boyutunu küçültmek ve dinamik renkler gibi dinamik kaynakları etkinleştirmek için doğrudan kaynak kimlikleri sağlamanızı öneririz.
Oluşturulabilir öğeler ve yöntemler, ImageProvider
gibi bir "sağlayıcı" veya GlanceModifier.background(R.color.blue)
gibi bir aşırı yükleme yöntemi kullanan kaynakları kabul eder. Örnek:
Column( modifier = GlanceModifier.background(R.color.default_widget_background) ) { /**...*/ } Image( provider = ImageProvider(R.drawable.ic_logo), contentDescription = "My image", )
Birleşik düğme ekleme
Birleşik düğmeler Android 12'de kullanıma sunuldu. Glance, aşağıdaki birleşik düğme türleri için geriye dönük uyumluluğu destekler:
Bu birleşik düğmelerin her biri, "işaretli" durumunu temsil eden tıklanabilir bir görünüm görüntüler.
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. Aşağıdaki örnekte gösterildiği gibi kontrol durumunu 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) } ) } }
Ayrıca CheckBox
, Switch
ve RadioButton
öğelerinin renklerini özelleştirmek 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) ), )