Auf dieser Seite wird beschrieben, wie mit Größen umgegangen wird und wie flexible und responsive Anzeigen bereitgestellt werden. Layouts mit Glance unter Verwendung vorhandener Glance-Komponenten erstellen.
Box
, Column
und Row
verwenden
Glance hat drei zusammensetzbare Hauptlayouts:
Box
: Platziert Elemente übereinander. Er wird inRelativeLayout
übersetzt.Column
: Platziert Elemente hintereinander in der vertikalen Achse. Übersetzung in einLinearLayout
mit vertikaler Ausrichtung.Row
: Platziert Elemente hintereinander in der horizontalen Achse. Übersetzung in einLinearLayout
mit horizontaler Ausrichtung.
Glance unterstützt Scaffold
-Objekte. Platziere Column
, Row
und
Box
-Zusammensetzbare Funktionen innerhalb eines bestimmten Scaffold
-Objekts.
Mit jeder dieser zusammensetzbaren Funktionen können Sie die vertikale und horizontale Ausrichtung festlegen. des Inhalts und die Einschränkungen für Breite, Höhe, Gewicht oder Abstände mithilfe von Modifizierern. Darüber hinaus kann jedes untergeordnete Element seinen Modifikator definieren, um das Leerzeichen Placement innerhalb des übergeordneten Elements.
Im folgenden Beispiel sehen Sie, wie Sie eine Row
erstellen, die gleichmäßig verteilt
seine untergeordneten Elemente horizontal, wie in Abbildung 1 dargestellt:
Row(modifier = GlanceModifier.fillMaxWidth().padding(16.dp)) { val modifier = GlanceModifier.defaultWeight() Text("first", modifier) Text("second", modifier) Text("third", modifier) }
Row
füllt die maximal verfügbare Breite aus. Da jedes untergeordnete Element dieselbe
teilen sie sich den verfügbaren Platz gleichmäßig. Sie können unterschiedliche Gewichtungen,
Größen, Abstände oder Ausrichtungen, um Layouts an Ihre Anforderungen anzupassen.
Scrollbare Layouts verwenden
Eine weitere Möglichkeit, responsive Inhalte bereitzustellen, besteht darin, sie scrollbar zu machen. Dies ist
mit der zusammensetzbaren Funktion LazyColumn
möglich. Mit dieser zusammensetzbaren Funktion können Sie
von Elementen, die in einem scrollbaren Container im App-Widget angezeigt werden.
Die folgenden Snippets zeigen verschiedene Möglichkeiten zum Definieren von Elementen im
LazyColumn
Sie können die Anzahl der Elemente angeben:
// Remember to import Glance Composables // import androidx.glance.appwidget.layout.LazyColumn LazyColumn { items(10) { index: Int -> Text( text = "Item $index", modifier = GlanceModifier.fillMaxWidth() ) } }
Stellen Sie einzelne Elemente bereit:
LazyColumn { item { Text("First Item") } item { Text("Second Item") } }
Geben Sie eine Liste oder ein Array von Elementen an:
LazyColumn { items(peopleNameList) { name -> Text(name) } }
Sie können auch eine Kombination der vorherigen Beispiele verwenden:
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") } }
Im vorherigen Snippet wurde itemId
nicht angegeben. Die Angabe des
itemId
hilft dabei, die Leistung zu verbessern und den Scrollvorgang beizubehalten
auf der Liste und appWidget
Updates ab Android 12 (für
z. B. wenn du Artikel hinzufügst oder entfernst. Im folgenden Beispiel
zeigt, wie ein itemId
angegeben wird:
items(items = peopleList, key = { person -> person.id }) { person -> Text(person.name) }
SizeMode
definieren
AppWidget
kann je nach Gerät, Nutzerauswahl oder Launcher variieren.
Daher ist es wichtig, flexible Layouts bereitzustellen, wie im Abschnitt Bereitstellung von
Seite „Flexible Widget-Layouts“ öffnen. Live-Anzeige erleichtert das mit der SizeMode
und den Wert LocalSize
. In den folgenden Abschnitten werden die drei
Modi.
SizeMode.Single
SizeMode.Single
ist der Standardmodus. Es bedeutet, dass nur eine Art von
Inhalte zur Verfügung gestellt werden, Das heißt, auch wenn sich die verfügbare Größe von AppWidget
ändert,
wird die Inhaltsgröße nicht geändert.
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 // ... } }
Achten Sie bei Verwendung dieses Modus auf Folgendes:
- Die Metadatenwerte für die Mindest- und Maximalgröße sind korrekt definiert, auf die Inhaltsgröße.
- Der Inhalt ist innerhalb des erwarteten Größenbereichs ausreichend flexibel.
Im Allgemeinen sollten Sie diesen Modus in folgenden Fällen verwenden:
a) AppWidget
eine feste Größe hat oder
b) Der Inhalt ändert sich bei der Größenanpassung nicht.
SizeMode.Responsive
Dieser Modus entspricht dem Bereitstellen responsiver Layouts, mit dem
GlanceAppWidget
, um einen Satz responsiver Layouts zu definieren, die durch bestimmte
Größen. Für jede definierte Größe wird der Inhalt erstellt und der spezifischen
festgelegt, wenn die AppWidget
erstellt oder aktualisiert wird. Das System wählt dann die
am besten geeignet für die verfügbare Größe sein.
In unserem Ziel AppWidget
können Sie beispielsweise drei Größen definieren und
Inhalt:
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") } } } }
Im vorherigen Beispiel wurde die Methode provideContent
dreimal aufgerufen und
definierter Größe zugeordnet ist.
- Im ersten Aufruf wird die Größe als
100x100
ausgewertet. Der Inhalt entspricht nicht die zusätzliche Schaltfläche und den Text oben und unten einfügen. - Im zweiten Aufruf wird die Größe als
250x100
ausgewertet. Der Inhalt umfasst die zusätzliche Schaltfläche, aber nicht den oberen und unteren Text. - Im dritten Aufruf wird die Größe als
250x250
ausgewertet. Der Inhalt umfasst die und beide Texte verwenden.
SizeMode.Responsive
ist eine Kombination der anderen beiden Modi und ermöglicht Ihnen,
Responsive Inhalte innerhalb vordefinierter Grenzen zu definieren. Im Allgemeinen bietet dieser Modus
ist besser und ermöglicht flüssigere Übergänge, wenn die AppWidget
-Größe angepasst wird.
Die folgende Tabelle zeigt den Wert der Größe in Abhängigkeit von SizeMode
und
die verfügbare Größe von AppWidget
:
Verfügbare Größe | 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 |
* Die genauen Werte dienen nur zu Demonstrationszwecken. |
SizeMode.Exact
SizeMode.Exact
entspricht der Bereitstellung exakter Layouts,
fordert den Inhalt GlanceAppWidget
jedes Mal an, wenn die verfügbare Größe von AppWidget
verfügbar ist
(z. B. wenn der Nutzer die Größe von AppWidget
auf dem Startbildschirm ändert)
Beispielsweise kann im Ziel-Widget eine zusätzliche Schaltfläche hinzugefügt werden, verfügbare Breite größer als ein bestimmter Wert ist.
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") } } } } }
Dieser Modus ist flexibler als die anderen, bietet aber auch Warnungen:
- Die
AppWidget
muss bei jeder Größenänderung vollständig neu erstellt werden. Dieses kann bei komplexen Inhalten zu Leistungsproblemen und Sprüngen der Benutzeroberfläche führen. - Die verfügbare Größe kann je nach Implementierung des Launchers variieren. Wenn im Launcher beispielsweise keine Liste mit Größen angezeigt wird, mögliche Größe verwendet.
- Bei Geräten mit einer älteren Version von Android 12 funktioniert die Logik zur Größenberechnung möglicherweise nicht bei allen Situationen.
Im Allgemeinen sollten Sie diesen Modus verwenden, wenn SizeMode.Responsive
nicht verwendet werden kann
(d. h., eine kleine Gruppe von responsiven Layouts ist nicht praktikabel.)
Auf Ressourcen zugreifen
Verwenden Sie LocalContext.current
, um auf jede Android-Ressource zuzugreifen, wie in der
folgendes Beispiel:
LocalContext.current.getString(R.string.glance_title)
Wir empfehlen, Ressourcen-IDs direkt anzugeben, um die Größe der endgültigen
RemoteViews
-Objekt zu erstellen und dynamische Ressourcen wie dynamische
Farben dargestellt wird.
Composables und Methoden akzeptieren Ressourcen mithilfe eines „Anbieters“, z. B.
ImageProvider
oder eine Überlastungsmethode wie
GlanceModifier.background(R.color.blue)
. Beispiel:
Column( modifier = GlanceModifier.background(R.color.default_widget_background) ) { /**...*/ } Image( provider = ImageProvider(R.drawable.ic_logo), contentDescription = "My image", )
Text verarbeiten
Glance 1.1.0 enthält eine API zum Festlegen Ihrer Textstile. Textstile festlegen mit
fontSize
-, fontWeight
- oder fontFamily
-Attribute der TextStyle-Klasse.
fontFamily
unterstützt alle Systemschriftarten, wie im folgenden Beispiel gezeigt, aber
benutzerdefinierte Schriftarten in Apps werden nicht unterstützt:
Text(
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
),
text = "Example Text"
)
Kombinierte Schaltflächen hinzufügen
Zusammengesetzte Schaltflächen wurden mit Android 12 eingeführt. Mit der Live-Anzeige können Sie Kompatibilität für die folgenden Arten von zusammengesetzten Schaltflächen:
Diese zusammengesetzten Schaltflächen zeigen jeweils eine klickbare Ansicht an, die das "aktiviert" Bundesstaat.
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" )
Wenn sich der Status ändert, wird das angegebene Lambda ausgelöst. Sie können die überprüfen, wie im folgenden Beispiel gezeigt:
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) } ) } }
Sie können das Attribut colors
auch für CheckBox
, Switch
und
RadioButton
, um die Farben anzupassen:
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) ), )
Zusätzliche Komponenten
Glance 1.1.0 enthält die Veröffentlichung zusätzlicher Komponenten, wie in den folgende Tabelle:
Name | Bild | Referenzlink | Zusätzliche Anmerkungen |
---|---|---|---|
Gefüllter Knopf | Komponente | ||
Umrissschaltflächen | Komponente | ||
Symbolschaltflächen | Komponente | Primär / Sekundär / Nur Symbol | |
Titelleiste | Komponente | ||
Gerüst | Gerüst und Titelleiste befinden sich in derselben Demo. |
Weitere Informationen zu den Design-Besonderheiten finden Sie in den Komponentendesigns in dieser Designkit für Figma.