Les sections suivantes expliquent comment créer un widget d'application de base avec Glance.
Déclarer l'AppWidget dans le fichier manifeste
Une fois les étapes de configuration terminées, déclarez l'AppWidget et ses
métadonnées dans votre application.
Étendez le
AppWidgetrécepteur à partir deGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
Enregistrez le fournisseur du widget d'application dans votre fichier
AndroidManifest.xmlet le fichier de métadonnées associé :<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>
Ajouter les métadonnées AppWidgetProviderInfo
Ensuite, suivez le guide Créer un widget pour créer et définir les informations du widget d'application
dans le fichier @xml/my_app_widget_info.
La seule différence pour Glance est qu'il n'existe pas de fichier XML initialLayout, mais vous devez en définir un. Vous pouvez utiliser la mise en page de chargement prédéfinie fournie dans la bibliothèque :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
Déclarer le fichier XML AppWidgetProviderInfo
L'objet AppWidgetProviderInfo définit les qualités essentielles de votre widget. Définissez le AppWidgetProviderInfo dans votre fichier de ressources de métadonnées XML
(res/xml/my_app_widget_info.xml) à l'intérieur d'un élément <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>
Attributs de dimensionnement des widgets
L'écran d'accueil par défaut positionne les widgets dans sa fenêtre en fonction d'une grille de cellules dont la hauteur et la largeur sont définies. La plupart des écrans d'accueil n'autorisent que les widgets dont la taille est un multiple entier des cellules de la grille (par exemple, deux cellules horizontalement sur trois verticalement).
Les attributs de dimensionnement des widgets vous permettent de spécifier une taille par défaut pour votre widget et de fournir des limites inférieure et supérieure pour sa taille. Dans ce contexte, la taille par défaut d'un widget est celle qu'il prend lorsqu'il est ajouté à l'écran d'accueil pour la première fois.
Le tableau suivant décrit les <appwidget-provider> attributs relatifs
au dimensionnement des widgets :
| Attributs et description | |
|---|---|
targetCellWidth et
targetCellHeight (Android 12),
minWidth et minHeight |
targetCellWidth et
targetCellHeight, ainsi que minWidth et
minHeight) afin que votre application puisse revenir à l'utilisation de
minWidth et minHeight si l'appareil de l'utilisateur
n'est pas compatible avec targetCellWidth et
targetCellHeight. Si elles sont compatibles, les
targetCellWidth et targetCellHeight attributs
sont prioritaires sur les minWidth et minHeight
attributs.
|
minResizeWidth et
minResizeHeight |
Spécifiez la taille minimale absolue du widget. Ces valeurs spécifient la
taille en dessous de laquelle le widget est illisible ou inutilisable. L'utilisation
de ces attributs permet à l'utilisateur de redimensionner le widget à une taille inférieure
à sa taille par défaut. L'attribut minResizeWidth est
ignoré s'il est supérieur à minWidth ou si le redimensionnement horizontal
n'est pas activé. Consultez
resizeMode. De même, l'
minResizeHeight attribut est ignoré s'il est supérieur à
minHeight ou si le redimensionnement vertical n'est pas activé. |
maxResizeWidth et
maxResizeHeight |
Spécifiez la taille maximale recommandée du widget. Si les valeurs ne sont pas
un multiple des dimensions des cellules de la grille, elles sont arrondies à la taille de cellule la plus proche. L'attribut maxResizeWidth est ignoré s'il est
inférieur à minWidth ou si le redimensionnement horizontal n'est pas
activé. Consultez resizeMode. De même,
l'attribut maxResizeHeight est ignoré s'il est inférieur
à minHeight ou si le redimensionnement vertical n'est pas activé.
Introduit dans Android 12. |
resizeMode |
Spécifie les règles selon lesquelles un widget peut être redimensionné. Vous pouvez utiliser cet
attribut pour rendre les widgets de l'écran d'accueil redimensionnables horizontalement, verticalement,
ou sur les deux axes. Les utilisateurs appuient de manière prolongée sur un widget pour afficher ses poignées de redimensionnement,
puis font glisser les poignées horizontales ou verticales pour modifier sa taille dans la
grille de mise en page. Les valeurs de l'attribut resizeMode incluent
horizontal, vertical et none. Pour
déclarer un widget comme redimensionnable horizontalement et verticalement, utilisez
horizontal|vertical. |
Exemple
Pour illustrer l'impact des attributs du tableau précédent sur le dimensionnement des widgets, supposons les spécifications suivantes :
- Une cellule de grille mesure 30 dp de large et 50 dp de haut.
- La spécification d'attribut suivante est fournie :
<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" />
À partir d'Android 12 :
Utilisez les attributs targetCellWidth et targetCellHeight comme taille par défaut du widget.
La taille du widget est de 2x2 par défaut. Il peut être redimensionné jusqu'à 2x1 ou 4x3.
Android 11 et versions antérieures :
Utilisez les attributs minWidth et minHeight pour calculer la taille par défaut du widget.
Largeur par défaut = Math.ceil(80 / 30) = 3
Hauteur par défaut = Math.ceil(80 / 50) = 2
La taille du widget est de 3x2 par défaut. Il peut être redimensionné jusqu'à 2x1 ou en plein écran.
Attributs de widget supplémentaires
Le tableau suivant décrit les attributs <appwidget-provider> relatifs
à des qualités autres que le dimensionnement des widgets.
| Attributs et description | |
|---|---|
updatePeriodMillis |
Définit la fréquence à laquelle le framework de widget demande une mise à jour à
GlanceAppWidgetReceiver en appelant la méthode de rappel onUpdate(). Nous vous recommandons d'effectuer des mises à jour aussi rarement que
possible (pas plus d'une fois par heure) pour économiser la batterie.
Pour en savoir plus, consultez la section Quand mettre à jour les widgets dans Gestion de l'état de Glance. |
initialLayout |
Pointe vers la ressource de mise en page qui définit la mise en page de chargement du widget avant le rendu des compositions de l'interface utilisateur Glance. Vous pouvez utiliser la mise en page de chargement prédéfinie fournie dans la bibliothèque : @layout/glance_default_loading_layout. |
configure |
Définit l'activité de configuration qui se lance lorsque l'utilisateur ajoute le widget. Consultez le guide Implémenter l'activité de configuration. |
description |
Spécifie la description à afficher pour votre widget dans le sélecteur de widgets. Introduit dans Android 12. |
previewLayout (Android 12) et previewImage (Android 11 et versions antérieures) |
|
autoAdvanceViewId |
Spécifie l'ID de vue de la sous-vue du widget qui est automatiquement avancée par l'hôte du widget. |
widgetCategory |
Déclare si votre widget peut être affiché sur l'écran d'accueil
(home_screen), l'écran de verrouillage (keyguard) ou les deux. Pour Android 5.0 et versions ultérieures, seule la valeur home_screen est valide. |
widgetFeatures |
Déclare les fonctionnalités compatibles avec le widget. Par exemple, si la configuration de votre widget est facultative, spécifiez configuration_optional et reconfigurable. |
Définir GlanceAppWidget
Créez une classe qui étend
consultez la section Utiliser des coroutines pour la sécurité principale.GlanceAppWidgetet remplace laprovideGlanceméthode. Il s'agit de la méthode dans laquelle vous pouvez charger les données nécessaires au rendu de votre 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") } } }
Instanciez-le dans
glanceAppWidgetsur votreGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
Vous avez maintenant configuré un AppWidget à l'aide de Glance.
Utiliser la classe GlanceAppWidgetReceiver pour gérer les diffusions de widgets
Le GlanceAppWidgetReceiver coordonne les diffusions de widgets et les mises à jour de l'état de la plate-forme
en étendant le AppWidgetProvider sous-jacent. Il reçoit les événements de la plate-forme lorsque votre widget est mis à jour, supprimé, activé ou désactivé, et les traduit en requêtes de cycle de vie Compose.
Déclarer un widget dans le fichier manifeste
Déclarez la sous-classe GlanceAppWidgetReceiver en tant que récepteur de diffusion dans votre fichier 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'élément <receiver> nécessite l'attribut android:name, qui spécifie
la classe de récepteur. Le récepteur doit accepter l'action de diffusion ACTION_APPWIDGET_UPDATE
à l'intérieur de <intent-filter>.
L'élément <meta-data> doit identifier son nom comme
android.appwidget.provider, et l'attribut android:resource doit pointer vers
votre ressource de métadonnées XML AppWidgetProviderInfo (@xml/my_app_widget_info).
Implémenter la classe GlanceAppWidgetReceiver
Dans Glance, vous étendez GlanceAppWidgetReceiver au lieu de AppWidgetProvider directement. Implémentez-le en liant votre récepteur à votre instance GlanceAppWidget. Les principaux rappels disponibles dans GlanceAppWidgetReceiver fonctionnent comme suit :
onUpdate(): automatiquement remplacé par Glance pour exécuter les mises à jour de la composition. Si vous remplacez manuellementonUpdate, vous devez appelersuper.onUpdatepour permettre à Glance de lancer correctement les threads de composition.onAppWidgetOptionsChanged(): appelé lorsque le widget est placé ou redimensionné pour la première fois. Glance lit les éléments du bundle d'options en arrière-plan afin que votre mise en page s'ajuste de manière transparente en fonction des dimensions d'exécution.onDeleted(Context, IntArray): appelé chaque fois qu'une instance de widget spécifique est supprimée par l'utilisateur.onEnabled(Context): déclenché lorsque la première instance de votre widget est créée. Idéal pour exécuter des migrations globales.onDisabled(Context): appelé lorsque la dernière instance active du fournisseur est supprimée.onReceive(Context, Intent): intercepte chaque diffusion de plate-forme avant des méthodes de rappel spécifiques. Vous devez vous assurer que toute logique de récepteur personnalisée que vous écrivez appellesuper.onReceive(context, intent)et ne doit jamais appelergoAsyncvous-même, car Glance achemine automatiquement le travail de manière asynchrone.
Recevoir des intents de diffusion de widgets
En arrière-plan, GlanceAppWidgetReceiver filtre et gère les intents de diffusion de widgets de plate-forme fondamentaux suivants :
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
Créer une interface utilisateur
L'extrait suivant montre comment créer l'interface utilisateur :
/* 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>() ) } } } }
L'exemple de code précédent effectue les opérations suivantes :
- Dans le
Columnde premier niveau, les éléments sont placés verticalement les uns après les autres. - Le
Columnétend sa taille pour correspondre à l'espace disponible (via leGlanceModifieret aligne son contenu en haut (verticalAlignment) et le centre horizontalement (horizontalAlignment). - Le contenu du
Columnest défini à l'aide du lambda. L'ordre est important.- Le premier élément du
Columnest un composantTextavec un remplissage de12.dp. - Le deuxième élément est un
Row, où les éléments sont placés horizontalement les uns après les autres, avec deuxButtonscentrés horizontalement (horizontalAlignment). L'affichage final dépend de l'espace disponible. L'image suivante montre un exemple de ce à quoi cela peut ressembler :
- Le premier élément du
Vous pouvez modifier les valeurs d'alignement ou appliquer différentes valeurs de modificateur (telles que le remplissage) pour modifier l'emplacement et la taille des composants. Consultez la documentation de référence pour obtenir la liste complète des composants, des paramètres et des modificateurs disponibles pour chaque classe.
Implémenter des angles arrondis
Android 12 introduit des paramètres système pour personnaliser dynamiquement les rayons d'angle de vos widgets d'application :
system_app_widget_background_radius: spécifie le rayon d'angle du conteneur d'arrière-plan du widget (jamais supérieur à 28 dp).- Rayon intérieur : pour éviter le découpage du contenu, calculez un rayon proportionnel pour votre contenu intérieur en fonction du contour de l'arrière-plan du système :
systemRadiusValue - widgetPadding
Dans Glance, vous pouvez appliquer dynamiquement des propriétés de dimensionnement du rayon d'angle dans la composition à l'aide de GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
Pour assurer la rétrocompatibilité sur les appareils équipés d'Android 11 (niveau d'API 30) ou version antérieure, implémentez des attributs personnalisés et des solutions de secours pour les ressources de thème personnalisées :
/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>