Bir Bakışta ile kullanıcı arayüzü oluşturma

Bu sayfada, boyutları yönetmenin yanı sıra esnek ve duyarlı mevcut Glance bileşenlerini kullanarak düzenler.

Box, Column ve Row kullanın

Glance'ta composable üç ana sayfa düzeni bulunur:

  • Box: Öğeleri başka bir öğenin üzerine yerleştirir. RelativeLayout diline çevrilir.

  • Column: Öğeleri dikey eksende birbirinden sonra yerleştirir. Çevirisi dikey yönlü bir LinearLayout.

  • Row: Öğeleri yatay eksende birbirinden sonra yerleştirir. Çevirisi yatay yönlü bir LinearLayout.

Glance, Scaffold nesnelerini destekler. Column, Row ve Belirli bir Scaffold nesnesi içinde Box composable.

Sütun, satır ve kutu düzeninin resmi.
Şekil 1. Sütun, Satır ve Kutu içeren düzen örnekleri.
ziyaret edin.

Bu composable'ların her biri dikey ve yatay hizalamaları tanımlamanıza olanak sağlar kullanarak genişlik, yükseklik, ağırlık veya dolgu kısıtlamalarını kullanabilirsiniz. Ayrıca her çocuk, alanı değiştirmek için değiştiricisini tanımlayabilir üst öğe içindeki yerleşimdir.

Aşağıdaki örnekte, eşit şekilde dağıtılan bir Row'nin nasıl oluşturulacağı gösterilmektedir Şekil 1'de gösterildiği gibi alt yatay olarak ayarlanır:

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 dolduruyor ve her alt öğe aynı kullanılabilir alanı eşit olarak paylaşırlar. Farklı ağırlıklar, boyutları, dolguları veya hizalamaları kullanarak düzenleri ihtiyaçlarınıza göre uyarlayabilirsiniz.

Kaydırılabilir düzenler kullanma

Duyarlı içerik sağlamanın bir başka yolu da kaydırılabilir hale getirmektir. Bu her şeyi LazyColumn composable ile yapabilirsiniz. Bu composable, önceden tanımlanmış uygulama widget'ında kaydırılabilir bir kapsayıcıda görüntülenecek öğe sayısı.

Aşağıdaki snippet'ler, LazyColumn

Öğ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 girin:

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 özelliğini belirtmediğini unutmayın. itemId, performansı iyileştirmeye ve kaydırmayı sürdürmeye yardımcı olur Android 12 ve sonraki sürümlerdeki appWidget güncellemeleri için ( (örneğin, listeye öğe eklerken veya listeden öğe kaldırırken). Aşağıdaki örnek itemId belirtecinin nasıl belirtileceğini gösterir:

items(items = peopleList, key = { person -> person.id }) { person ->
    Text(person.name)
}

SizeMode tanımlayın

AppWidget boyutları cihaza, kullanıcının tercihine veya başlatıcıya göre değişiklik gösterebilir. Bu nedenle, Esnek widget düzenleri sayfasını ziyaret edin. Glance, SizeMode ile bu işlemi basitleştiriyor ve LocalSize değerini çağırın. Aşağıdaki bölümlerde bu üç unsur, kullanabilirsiniz.

SizeMode.Single

SizeMode.Single varsayılan moddur. Yalnızca tek bir tür içerik sağlanır; yani AppWidget kullanılabilir boyut değişse bile içeriğin boyutu değiştirilmez.

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, dikkat edin.
  • İçerik, beklenen boyut aralığında yeterince esnek olmalıdır.

Genel olarak bu modu aşağıdaki durumlardan birinde kullanmalısınız:

a) AppWidget sabit boyutludur veya b) yeniden boyutlandırıldığında içeriğini değiştirmez.

SizeMode.Responsive

Bu mod, duyarlı düzenler sağlama ile eşdeğerdir. belirliGlanceAppWidget seçin. Tanımlanan her boyut için içerik oluşturulur ve ilgili boyuta eşlenir. AppWidget oluşturulduğunda veya güncellendiğinde boyut. Sistem daha sonra mevcut boyuta göre en uygun olanı seçin.

Örneğin, AppWidget hedefimizde üç boyut tanımlayabilirsiniz ve içerik:

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")
            }
        }
    }
}

Yukarıdaki örnekte, provideContent yöntemi üç kez çağrılır ve tanımlanan boyutla eşleştirilir.

  • İlk çağrıda boyut 100x100 olarak değerlendirilir. İçerik ekstra düğmeyi ya da üst ve alt metinleri ekleyin.
  • İkinci çağrıda, boyut 250x100 olarak değerlendirilir. İçerik şunları içeriyor: ancak üst ve alt metinleri değil, yalnızca ekstra düğme kullanabilirsiniz.
  • Üçüncü çağrıda boyut 250x250 olarak değerlendirilir. İçerik şunları içeriyor: fazladan düğmeyi ve her iki metni de içerir.

SizeMode.Responsive, diğer iki modun birleşiminden oluşur ve aşağıdakilerden hangisini yapmanıza olanak tanır? Önceden tanımlanmış sınırlar içinde duyarlı içerik tanımlama. Genel olarak, bu mod AppWidget yeniden boyutlandırıldığında daha iyi performans gösterir ve daha yumuşak geçişler sağlar.

Aşağıdaki tabloda, boyutun değeri SizeMode ve kullanılabilir AppWidget boyut:

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 eşdeğerdir. kullanılabilir AppWidget boyutunda her seferinde GlanceAppWidget içeriğini ister (örneğin, kullanıcı ana ekranda AppWidget öğesini yeniden boyutlandırdığında).

Örneğin, hedef widget'ta belirli bir değerden büyük olması gerekir.

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ğlasa da bazı özellikler dikkat edilecek noktalar:

  • Boyut her değiştiğinde AppWidget tamamen yeniden oluşturulmalıdır. Bu İç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ı bir boyut listesi sağlamazsa, minimum boyut boyutu kullanılır.
  • Boyut hesaplama mantığı, Android 12 sürümünden önceki tüm cihazlarda çalışmayabilir. durumlardan birine sahip olmaları halinde başlatabilirler.

Genel olarak, SizeMode.Responsive kullanılamıyorsa bu modu kullanmalısınız. (yani, küçük bir duyarlı düzen grubu uygun değildir).

Kaynaklara erişin

İstediğiniz Android kaynağına erişmek için LocalContext.current kullanın. Örneğin: şu örneği inceleyin:

LocalContext.current.getString(R.string.glance_title)

Nihai dosyanın boyutunu küçültmek için doğrudan kaynak kimliklerinin sağlanmasını RemoteViews nesnesini oluşturmak ve dinamik kaynakları (ör. dinamik) etkinleştirmek için renkler arasından seçim yapın.

Oluşturulabilirler ve yöntemler, ImageProvider veya şunun gibi bir aşırı yükleme yöntemi kullanarak: GlanceModifier.background(R.color.blue). Ö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 ayarlayabileceğiniz bir API içerir. Metin stillerini şununla ayarlayın: TextStyle sınıfının fontSize, fontWeight veya fontFamily özellikleri.

fontFamily, aşağıdaki örnekte gösterildiği gibi tüm sistem yazı tiplerini destekler, ancak uygulamalarda özel yazı tipleri desteklenmez:

Text(
    style = TextStyle(
        fontWeight = FontWeight.Bold,
        fontSize = 18.sp,
        fontFamily = FontFamily.Monospace
    ),
    text = "Example Text"
)

Bileşik düğme ekle

Bileşik düğmeler Android 12'de kullanıma sunuldu. Bir Bakışta, geriye dönük verileri destekler aşağıdaki bileşik düğme türleri için uyumluluk:

Bu birleşik düğmelerin her biri, düğmeyi temsil eden tıklanabilir bir görünümü "işaretlendi" durumu.

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. Bu e-posta adresini durumu kontrol edin:

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) }
        )
    }
}

colors özelliğini CheckBox, Switch ve Renklerini özelleştirmek için RadioButton:

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, şurada açıklandığı gibi ek bileşenlerin yayınlanmasını içerir: aşağıdaki tabloda bulabilirsiniz:

Ad Resim Referans bağlantısı Ek notlar
Doldurulmuş Düğme alternatif_metin Bileşen
Dış Çizgi Düğmeler alternatif_metin Bileşen
Simge Düğmeleri alternatif_metin Bileşen Birincil / İkincil / Yalnızca simge
Başlık Çubuğu alternatif_metin Bileşen
İskele İskele ve Başlık çubuğu aynı demodadır.

Tasarım ayrıntıları hakkında daha fazla bilgi için bu tasarım kitini inceleyin.