Le sezioni seguenti descrivono come creare un widget dell'app di base con Glance.
Dichiarare AppWidget nel file manifest
Dopo aver completato i passaggi di configurazione, dichiara AppWidget e i relativi
metadati nella tua app.
Estendi il
AppWidgetricevitore daGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
Registra il provider del widget dell'app nel file
AndroidManifest.xmle nel file di metadati associato:<receiver android:name=".glance.MyReceiver" android:exported="true"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/my_app_widget_info" /> </receiver>
Aggiungere i metadati AppWidgetProviderInfo
Poi, segui la guida Creare un widget per creare e definire le informazioni del widget dell'app
nel file @xml/my_app_widget_info.
L'unica differenza per Glance è che non esiste un file XML initialLayout, ma devi definirne uno. Puoi utilizzare il layout di caricamento predefinito fornito nella libreria:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
Dichiarare il file XML AppWidgetProviderInfo
L'oggetto AppWidgetProviderInfo definisce le qualità essenziali del widget. Definisci AppWidgetProviderInfo nel file di risorse dei metadati XML
(res/xml/my_app_widget_info.xml) all'interno di un elemento <appwidget-provider>:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/glance_default_loading_layout"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
Attributi di dimensionamento dei widget
La schermata Home predefinita posiziona i widget nella finestra in base a una griglia di celle con altezza e larghezza definite. La maggior parte delle schermate Home consente ai widget di assumere solo dimensioni che sono multipli interi delle celle della griglia, ad esempio due celle in orizzontale per tre celle in verticale.
Gli attributi di dimensionamento dei widget ti consentono di specificare una dimensione predefinita per il widget e di fornire limiti inferiori e superiori per le dimensioni del widget. In questo contesto, la dimensione predefinita di un widget è la dimensione che il widget assume quando viene aggiunto per la prima volta alla schermata Home.
La tabella seguente descrive gli attributi <appwidget-provider> relativi
al dimensionamento dei widget:
| Attributi e descrizione | |
|---|---|
targetCellWidth e
targetCellHeight (Android 12),
minWidth e minHeight |
targetCellWidth e
targetCellHeight, e minWidth e
minHeight—in modo che la tua app possa utilizzare
minWidth e minHeight se il dispositivo dell'utente
non supporta targetCellWidth e
targetCellHeight. Se supportati, gli attributi targetCellWidth e targetCellHeight hanno la precedenza sugli attributi minWidth e minHeight.
|
minResizeWidth e
minResizeHeight |
Specifica la dimensione minima assoluta del widget. Questi valori specificano la
dimensione al di sotto della quale il widget è illeggibile o inutilizzabile. L'utilizzo di
questi attributi consente all'utente di ridimensionare il widget a una dimensione inferiore
a quella predefinita. L'attributo minResizeWidth viene
ignorato se è maggiore di minWidth o se il ridimensionamento orizzontale
non è attivato. Vedi
resizeMode. Allo stesso modo, l'
attributo minResizeHeightviene ignorato se è maggiore di
minHeight o se il ridimensionamento verticale non è attivato. |
maxResizeWidth e
maxResizeHeight |
Specifica la dimensione massima consigliata del widget. Se i valori non sono
un multiplo delle dimensioni delle celle della griglia, vengono arrotondati per eccesso alla dimensione della cella più vicina. L'attributo maxResizeWidth viene ignorato se è
inferiore a minWidth o se il ridimensionamento orizzontale non è
attivato. Vedi resizeMode. Allo stesso modo,
l'attributo maxResizeHeight viene ignorato se è inferiore
a minHeight o se il ridimensionamento verticale non è attivato.
Introdotto in Android 12. |
resizeMode |
Specifica le regole in base alle quali è possibile ridimensionare un widget. Puoi utilizzare questo
attributo per rendere i widget della schermata Home ridimensionabili in orizzontale, in verticale,
o su entrambi gli assi. Gli utenti toccano e tengono premuto un widget per visualizzare le maniglie di ridimensionamento,
quindi trascinano le maniglie orizzontali o verticali per modificarne le dimensioni nella
griglia di layout. I valori dell'attributo resizeMode includono
horizontal, vertical e none. Per
dichiarare un widget come ridimensionabile in orizzontale e in verticale, utilizza
horizontal|vertical. |
Esempio
Per illustrare in che modo gli attributi della tabella precedente influiscono sul dimensionamento dei widget, supponiamo le seguenti specifiche:
- Una cella della griglia ha una larghezza di 30 dp e un'altezza di 50 dp.
- Viene fornita la seguente specifica dell'attributo:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
A partire da Android 12:
Utilizza gli attributi targetCellWidth e targetCellHeight come dimensione predefinita del widget.
Per impostazione predefinita, le dimensioni del widget sono 2x2. Il widget può essere ridimensionato fino a 2x1 o fino a 4x3.
Android 11 e versioni precedenti:
Utilizza gli attributi minWidth e minHeight per calcolare la dimensione predefinita del widget.
Larghezza predefinita = Math.ceil(80 / 30) = 3
Altezza predefinita = Math.ceil(80 / 50) = 2
Per impostazione predefinita, le dimensioni del widget sono 3x2. Il widget può essere ridimensionato fino a 2x1 o fino a schermo intero.
Attributi aggiuntivi dei widget
La tabella seguente descrive gli attributi <appwidget-provider> relativi
a qualità diverse dal dimensionamento dei widget.
| Attributi e descrizione | |
|---|---|
updatePeriodMillis |
Definisce la frequenza con cui il framework dei widget richiede un aggiornamento da
GlanceAppWidgetReceiver chiamando il metodo di callback onUpdate(). Ti consigliamo di eseguire gli aggiornamenti il meno frequentemente possibile
non più di una volta all'ora, per risparmiare la batteria.
Per maggiori dettagli, consulta la sezione Quando aggiornare i widget in Gestione dello stato di Glance. |
initialLayout |
Punta alla risorsa di layout che definisce il layout di caricamento del widget prima del rendering delle composizioni dell'UI di Glance. Puoi utilizzare il layout di caricamento predefinito fornito nella libreria: @layout/glance_default_loading_layout. |
configure |
Definisce l'attività di configurazione che viene avviata quando l'utente aggiunge il widget. Consulta la guida Implementare l'attività di configurazione. |
description |
Specifica la descrizione da visualizzare per il widget nel selettore di widget. Introdotto in Android 12. |
previewLayout (Android 12) e previewImage (Android 11 e versioni precedenti) |
|
autoAdvanceViewId |
Specifica l'ID della visualizzazione della sottovista del widget che viene avanzata automaticamente dall'host del widget. |
widgetCategory |
Dichiara se il widget può essere visualizzato nella schermata Home
(home_screen), nella schermata di blocco (keyguard) o in entrambe. Per Android 5.0 e versioni successive, è valido solo home_screen. |
widgetFeatures |
Dichiara le funzionalità supportate dal widget. Ad esempio, se la configurazione del widget è facoltativa, specifica sia configuration_optional sia reconfigurable. |
Definire GlanceAppWidget
Crea una nuova classe che estenda da
GlanceAppWidgete sostituisca il metodoprovideGlance. Questo è il metodo in cui puoi caricare i dati necessari per il rendering del widget:class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // In this method, load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here Text("Hello World") } } }
Crea un'istanza in
glanceAppWidgetsuGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
A questo punto, hai configurato un AppWidget utilizzando Glance.
Utilizzare la classe GlanceAppWidgetReceiver per gestire le trasmissioni dei widget
La classe GlanceAppWidgetReceiver coordina le trasmissioni dei widget e gli aggiornamenti dello stato della piattaforma
estendendo la classe AppWidgetProvider sottostante. Riceve gli eventi della piattaforma quando il widget viene aggiornato, eliminato, attivato o disattivato, traducendoli in richieste del ciclo di vita di Compose.
Dichiarare un widget nel file manifest
Dichiara la sottoclasse GlanceAppWidgetReceiver come broadcast receiver nel file AndroidManifest.xml:
<receiver android:name="MyReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>
L'elemento <receiver> richiede l'attributo android:name, che specifica
la classe del ricevitore. Il ricevitore deve accettare l'azione di trasmissione ACTION_APPWIDGET_UPDATE
all'interno di <intent-filter>.
L'elemento <meta-data> deve identificare il proprio nome come
android.appwidget.provider e l'attributo android:resource deve puntare a
alla risorsa dei metadati XML AppWidgetProviderInfo (@xml/my_app_widget_info).
Implementare la classe GlanceAppWidgetReceiver
In Glance, estendi GlanceAppWidgetReceiver anziché AppWidgetProvider direttamente. Implementalo collegando il ricevitore all'istanza GlanceAppWidget. I callback principali disponibili in GlanceAppWidgetReceiver funzionano nel seguente modo:
onUpdate(): sostituito automaticamente da Glance per eseguire gli aggiornamenti della composizione. Se sostituisci manualmenteonUpdate, devi chiamaresuper.onUpdateper consentire a Glance di avviare correttamente i thread di composizione.onAppWidgetOptionsChanged(): chiamato quando il widget viene posizionato o ridimensionato per la prima volta. Glance legge gli elementi del bundle di opzioni in background, in modo che il layout si adatti perfettamente in base alle dimensioni di runtime.onDeleted(Context, IntArray): richiamato ogni volta che l'utente elimina un'istanza specifica del widget.onEnabled(Context): attivato quando la prima istanza del widget viene creata correttamente. Ideale per eseguire migrazioni globali.onDisabled(Context): chiamato quando viene rimossa l'ultima istanza attiva del provider.onReceive(Context, Intent): intercetta ogni trasmissione della piattaforma prima di metodi di callback specifici. Devi assicurarti che la logica del ricevitore personalizzato che scrivi chiamisuper.onReceive(context, intent)e non deve mai chiamaregoAsync, perché Glance instrada automaticamente il lavoro in modo asincrono.
Ricevere intent di trasmissione dei widget
In background, GlanceAppWidgetReceiver filtra e gestisce i seguenti intent di trasmissione dei widget della piattaforma di base:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
Creare UI
Il seguente snippet mostra come creare l'UI:
/* Import Glance Composables In the event there is a name clash with the Compose classes of the same name, you may rename the imports per https://kotlinlang.org/docs/packages.html#imports using the `as` keyword. import androidx.glance.Button import androidx.glance.layout.Column import androidx.glance.layout.Row import androidx.glance.text.Text */ class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // Load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here MyContent() } } @Composable private fun MyContent() { Column( modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button( text = "Home", onClick = actionStartActivity<MyActivity>() ) Button( text = "Work", onClick = actionStartActivity<MyActivity>() ) } } } }
Il codice di esempio precedente esegue le seguenti operazioni:
- Nella
Columndi primo livello, gli elementi vengono posizionati verticalmente uno dopo l'altro. - Il
Columnespande le dimensioni in modo che corrispondano allo spazio disponibile (tramiteGlanceModifiere allinea i contenuti alla parte superiore (verticalAlignment) e li centra orizzontalmente (horizontalAlignment). - I contenuti di
Columnvengono definiti utilizzando l'espressione lambda. l'ordine è importante.- Il primo elemento in
Columnè un componenteTextcon un padding di12.dp. - Il secondo elemento è una
Row, in cui gli elementi vengono posizionati orizzontalmente uno dopo l'altro, con dueButtonscentrati orizzontalmente (horizontalAlignment). La visualizzazione finale dipende dallo spazio disponibile. L'immagine seguente è un esempio di come potrebbe apparire:
- Il primo elemento in
Puoi modificare i valori di allineamento o applicare valori di modificatore diversi (ad esempio il padding) per modificare il posizionamento e le dimensioni dei componenti. Consulta la documentazione di riferimento per un elenco completo di componenti, parametri e modificatori disponibili per ogni classe.
Implementare gli angoli arrotondati
Android 12 introduce parametri di sistema per personalizzare dinamicamente i raggi degli angoli dei widget dell'app:
system_app_widget_background_radius: specifica il raggio dell'angolo del contenitore dello sfondo del widget (non superiore a 28 dp).- Raggio interno: per evitare il ritaglio dei contenuti, calcola un raggio proporzionale per i contenuti interni in base al contorno dello sfondo del sistema:
systemRadiusValue - widgetPadding
In Glance, puoi applicare dinamicamente le proprietà di dimensionamento del raggio dell'angolo nella composizione utilizzando GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
Per la compatibilità con le versioni precedenti sui dispositivi che eseguono Android 11 (livello API 30) o versioni precedenti, implementa attributi personalizzati e fallback delle risorse dei temi personalizzati:
/values/attrs.xml<resources> <attr name="backgroundRadius" format="dimension" /> </resources>/values/styles.xml<resources> <style name="MyWidgetTheme"> <item name="backgroundRadius">@dimen/my_background_radius_dimen</item> </style> </resources>/values-31/styles.xml<resources> <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight"> <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item> </style> </resources>/drawable/my_widget_background.xml<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="?attr/backgroundRadius" /> </shape>