Bu sayfada, mevcut Glance bileşenlerini kullanarak Glance ile boyutların nasıl işleneceği ve esnek ve duyarlı düzenlerin nasıl sağlanacağı açıklanmaktadır.
Box, Column ve Row özelliğini kullanma
Glance'in üç ana composable düzeni vardır:
Box: Öğeleri birbirinin üzerine yerleştirir. Bu,RelativeLayoutanlamına gelir.Column: Öğeleri dikey eksende birbirinin arkasına yerleştirir. Bu, dikey yönlü birLinearLayoutolarak çevrilir.Row: Öğeleri yatay eksende yan yana yerleştirir. Bu, yatay yönlü birLinearLayoutolarak çevrilir.
Bir Bakışta özelliği Scaffold nesnelerini destekler. Column, Row ve Box composable'larınızı belirli bir Scaffold nesnesinin içine yerleştirin.
Bu composable'ların her biri, değiştiricileri kullanarak içeriğinin dikey ve yatay hizalamalarını, genişliğini, yüksekliğini, ağırlığını veya dolgu kısıtlamalarını tanımlamanıza olanak tanır. Ayrıca her alt öğe, üst öğenin içindeki alanı ve yerleşimi değiştirmek için kendi 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ğı açıklanmaktadır:
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 mevcut alanı eşit şekilde paylaşırlar. 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 kullanma
Duyarlı içerik sunmanın bir diğer yolu da içeriği kaydırılabilir hale getirmektir. Bu, LazyColumn composable ile mümkündür. Bu composable, uygulama widget'ında kaydırılabilir bir container içinde gösterilecek öğeler kümesini 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() ) } }
Ayrı ayrı öğeler sağlama:
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
Öğe listesi veya dizisi sağlayın:
LazyColumn { items(peopleNameList) { name -> Text(name) } }
Ayrıca 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'te itemId belirtilmediğini unutmayın. itemId belirtmek, performansı artırmaya ve Android 12'den itibaren liste ve appWidget güncellemeleri (ör. listeye öğe ekleme veya listeden öğe kaldırma) sırasında kaydırma konumunu korumaya yardımcı olur. Aşağıdaki örnekte, itemId nasıl belirtileceği gösterilmektedir:
items(items = peopleList, itemId = { person -> person.id.hashCode().toLong() }) { person -> Text(person.name) }
Snap Scrolling
Snap scrolling, kaydırılabilir içeriğin widget kapsayıcısının en üstüne yerleşmesini sağlayan bir animasyondur.
Anında kaydırma özelliğini uygulamak için aşağıdaki koşulları karşıladığınızdan emin olun:
- Glance bağımlılığınızı 1.3.0-alpha02 veya sonraki bir sürüme güncelleyin.
- Android 17 ve sonraki sürümlerin yüklü olduğu cihazlarda hızlı kaydırma desteklendiğinden
compileSdkayarınızı 37 veya daha yüksek bir değere ayarlayın. LazyColumncihazınızıVerticalScrollModeile yapılandırın. Cihaz, hızlı kaydırma özelliğini destekliyorsaSnapScrollMatchHeightsimgesini kullanın. Aksi takdirde,Normalkullanın.
Resimlerle birlikte hızlı kaydırma kullanıyorsanız taşan resim Standart Düzen'e bakın.
@Composable fun SnapScrollLayout() { val height = LocalSize.current.height val items = listOf( ColorItem(Color.Red, "Red"), ColorItem(Color.Yellow, "Yellow"), ColorItem(Color.Blue, "Blue") ) val scrollMode = if (Build.VERSION.SDK_INT >= 37) { VerticalScrollMode.SnapScrollMatchHeight(height) } else { VerticalScrollMode.Normal } LazyColumn( verticalScrollMode = scrollMode ) { items(items) { item -> ColorCard(item, height) } } } @Composable private fun ColorCard(item: ColorItem, height: Dp) { Box( modifier = GlanceModifier .background(item.color) .fillMaxWidth() .height(height), contentAlignment = Alignment.Center ) { Text( text = item.name, modifier = GlanceModifier.background(Color.White) ) } }
SizeMode tanımlayın
AppWidget boyutları cihaza, kullanıcı tercihine veya başlatıcıya göre 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ğeriyle bu süreci 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ı gösterir. Yani, AppWidget kullanılabilir boyut 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 ş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 şu durumlarda kullanmalısınız:
a) AppWidget sabit bir boyuta sahipse veya
b) yeniden boyutlandırıldığında içeriğini değiştirmiyorsa.
SizeMode.Responsive
Bu mod, duyarlı düzenler sağlamaya eşdeğerdir. Bu sayede GlanceAppWidget, belirli boyutlarla sınırlanmış bir dizi duyarlı düzen tanımlayabilir. İçerik, tanımlanan her boyut için oluşturulur ve AppWidget oluşturulduğunda veya güncellendiğinde belirli bir boyuta eşlenir. Sistem daha sonra mevcut boyuta göre en uygun olanı seçer.
Örneğin, hedefimizde AppWidget üç 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
100x100olarak değerlendirilir. İçerikte ek düğme, üst ve alt metinler yer almıyor. - İkinci çağrıda boyut
250x100olarak değerlendirilir. İçerikte ek düğme var ancak üst ve alt metinler yok. - Üçüncü çağrıda boyut
250x250olarak değerlendirilir. İçerikte ek düğme ve her iki metin de yer alıyor.
SizeMode.Responsive, diğer iki modun birleşimidir ve önceden tanımlanmış sınırlar içinde duyarlı içerik tanımlamanıza olanak tanır. Genel olarak bu mod, AppWidget yeniden boyutlandırıldığında daha iyi performans gösterir ve daha sorunsuz geçişlere olanak tanır.
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 düzenler sağlama ile eşdeğerdir. Bu, GlanceAppWidget içeriğinin, kullanılabilir AppWidget boyutu her değiştiğinde (örneğin, kullanıcı ana ekrandaki AppWidget boyutunu değiştirdiğinde) istenmesini sağlar.
Örneğin, kullanılabilir genişlik belirli bir değerden büyükse hedef widget'ına 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ğerlerine göre daha fazla esneklik sağlar ancak bazı dezavantajları vardır:
- Boyut her değiştiğinde
AppWidgettamamen yeniden oluşturulmalıdır. Bu durum, içerik karmaşık olduğunda performans sorunlarına ve kullanıcı arayüzünde atlamalara yol açabilir. - Kullanılabilir boyut, başlatıcının uygulanmasına bağlı olarak değişebilir. Örneğin, başlatıcı boyut listesini sağlamıyorsa mümkün olan en küçük boyut kullanılır.
- Android 12'den önceki cihazlarda, boyut hesaplama mantığı her durumda çalışmayabilir.
Genel olarak, SizeMode.Responsive kullanılamıyorsa (yani duyarlı düzenlerin küçük bir 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)
Son RemoteViews nesnesinin boyutunu küçültmek ve dinamik renkler gibi dinamik kaynakları etkinleştirmek için kaynak kimliklerini doğrudan sağlamanızı öneririz.
Composable'lar ve yöntemler, ImageProvider gibi bir "sağlayıcı" veya GlanceModifier.background(R.color.blue) gibi bir aşırı yükleme yöntemi kullanarak kaynakları kabul eder. Örneğin:
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"
)
Bileşik düğmeler ekleme
Bileşik düğmeler Android 12'de kullanıma sunuldu. Glance, aşağıdaki bileşik düğme türleri için geriye dönük uyumluluğu destekler:
Bu bileşik düğmelerin her biri, "işaretli" durumunu temsil eden 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 { mutableIntStateOf(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, işaretleme 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, renklerini özelleştirmek için colors özelliğini CheckBox, Switch ve RadioButton için 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 |
|---|---|---|---|
| Dolu 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 | İskele ve başlık çubuğu aynı demoda yer alıyor. |
Tasarım ayrıntıları hakkında daha fazla bilgi için Figma'daki bu tasarım kitinde yer alan 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.