Bu sayfada, mevcut Glance bileşenlerini kullanarak boyutları nasıl yöneteceğiniz ve Glance ile esnek ve duyarlı düzenleri nasıl sağlayacağınız açıklanmaktadır.
Box, Column ve Row kullanın
Glance'in üç ana composable düzeni vardır:
Box: Öğeleri üst üste yerleştirir. Bu,RelativeLayoutanlamına gelir.Column: Öğeleri dikey eksende birbiri ardına yerleştirir. Bu, dikey yönlendirmeli birLinearLayoutanlamına gelir.Row: Öğeleri yatay eksende birbirinin ardına yerleştirir. Yatay yönlendirmeli birLinearLayoutolarak çevrilir.
Glance, Scaffold nesnelerini destekler. Column, Row ve Box composable'larınızı belirli bir Scaffold nesnesine yerleştirin.
Bu composable'ların her biri, değiştiricileri kullanarak içeriğinin dikey ve yatay hizalamalarını ve genişlik, yükseklik, ağırlık veya dolgu kısıtlamalarını tanımlamanıza olanak tanır. Ayrıca her alt öğe, üst öğe içindeki boşluğu ve yerleşimi değiştirmek için kendi değiştiricisini tanımlayabilir.
Aşağıdaki örnekte, alt öğelerini Şekil 1'de gösterildiği gibi yatay olarak eşit şekilde dağıtan bir Row oluşturma işlemi 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ğundan 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üzenleri kullanma
Uyumlu içerik sunmanın bir başka yolu da içeriği kaydırılabilir hale getirmektir. Bunu LazyColumn composable'ı ile yapabilirsiniz. Bu composable, uygulama widget'ındaki kaydırılabilir bir kapsayıcıda gösterilecek 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ğlama:
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
Öğ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'te itemId belirtilmediğini unutmayın. itemId değerini belirtmek, Android 12'den itibaren liste ve appWidget güncellemeleri aracılığıyla performansı iyileştirmeye ve kaydırma konumunu korumaya yardımcı olur (örneğin, listeye öğe eklerken veya listeden öğe kaldırırken). Aşağıdaki örnekte, itemId öğesinin nasıl belirtileceği gösterilmektedir:
items( items = peopleList, itemId = { person -> person.id.hashCode().toLong() }) { person -> Text(person.name) }
Snap Scrolling
Kaydırarak sabitleme, kaydırılabilir içeriğin widget kapsayıcısının üst kısmına sabitlenmesini sağlayan bir animasyondur.
Kaydırarak geçiş ö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.
- Kaydırarak geçiş özelliği Android 17 ve sonraki sürümleri çalıştıran cihazlarda desteklendiğinden
compileSdkdeğerini 37 veya daha yüksek bir değere ayarlayın. LazyColumncihazınızıVerticalScrollModeile yapılandırın. Cihaz, kaydırma özelliğini destekliyorsaSnapScrollMatchHeightkullanın. Aksi takdirdeNormalözelliğini kullanın.
Resimlerle kaydırma özelliğini kullanıyorsanız tam sayfa resim standart düzenine 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 farklılık gösterebilir. 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 bu üç 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 şunlardan 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 esnek.
Genel olarak bu modu aşağıdaki durumlarda kullanmalısınız:
a) AppWidget sabit bir boyuta sahipse veya
b) Yeniden boyutlandırıldığında içeriği değişmiyorsa.
SizeMode.Responsive
Bu mod, duyarlı düzenler sağlamanın eşdeğeridir. GlanceAppWidget, belirli boyutlarla sınırlı bir dizi duyarlı düzen tanımlayabilir. Tanımlanan her boyut için içerik oluşturulur ve AppWidget oluşturulduğunda veya güncellendiğinde belirli boyuta eşlenir. Sistem daha sonra mevcut boyuta göre en uygun olanı seçer.
Örneğin, AppWidget hedefimizde üç boyut ve bunların 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 ekstra düğme, üst ve alt metinler yer almaz. - İkinci çağrıda boyut
250x100olarak değerlendirilir. İçerikte ekstra düğme var ancak üst ve alt metinler yok. - Üçüncü çağrıda boyut
250x250olarak değerlendirilir. İçerikte ekstra düğme ve her iki metin de yer alır.
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 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 kullanılabilir AppWidget boyutuna bağlı olarak boyutun değeri gösterilmektedir:
| Mevcut 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 tanıtım amaçlıdır. |
SizeMode.Exact
SizeMode.Exact, tam düzenler sağlamanın eşdeğeridir. Bu, kullanılabilir AppWidget boyutu her değiştiğinde (örneğin, kullanıcı ana ekranda AppWidget boyutunu değiştirdiğinde) GlanceAppWidget içeriğini ister.
Örneğin, hedef widget'ında kullanılabilir genişlik belirli bir değerden büyükse ekstra 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 birkaç uyarıyı da beraberinde getirir:
- 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 uygulamasına bağlı olarak farklılık gösterebilir. Örneğin, başlatıcı boyut listesini sağlamıyorsa 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 bu modu kullanmanız gerekir (yani, küçük bir duyarlı düzen grubu uygun değildir).
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 küçültmek ve dinamik renkler gibi dinamik kaynakları etkinleştirmek için kaynak kimliklerini doğrudan sağlamanızı öneririz.
Birleştirilebilir öğeler 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. Ö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" durumu 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şaretli durumu 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 colors özelliğini CheckBox, Switch ve RadioButton öğelerine de ekleyebilirsiniz:
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 |
|---|---|---|---|
| Dolgulu Düğme |
|
Bileşen | |
| Ana Hat Düğmeleri |
|
Bileşen | |
| Simge Düğmeleri |
|
Bileşen | Birincil / İkincil / Yalnızca simge |
| Başlık Çubuğu |
|
Bileşen | |
| İskele | Scaffold ve başlık çubuğu aynı demoda yer alır. |
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.