Cette page décrit les améliorations apportées au dimensionnement des widgets et la plus grande flexibilité introduite dans Android 12 (niveau d'API 31). Il explique également comment déterminer la taille de votre widget.
Utiliser des API améliorées pour les tailles et les mises en page des widgets
À partir d'Android 12 (niveau d'API 31), vous pouvez fournir des attributs de taille plus précis et des mises en page flexibles en procédant comme suit, comme décrit dans les sections suivantes :
Spécifiez des contraintes de dimensionnement supplémentaires pour le widget.
Fournir des mises en page responsives ou des mises en page exactes.
Dans les versions précédentes d'Android, il est possible d'obtenir les plages de tailles d'un widget à l'aide des extras OPTION_APPWIDGET_MIN_WIDTH, OPTION_APPWIDGET_MIN_HEIGHT, OPTION_APPWIDGET_MAX_WIDTH et OPTION_APPWIDGET_MAX_HEIGHT, puis d'estimer la taille du widget. Toutefois, cette logique ne fonctionne pas dans toutes les situations. Pour les widgets ciblant Android 12 ou version ultérieure, nous vous recommandons de fournir des mises en page responsives ou exactes.
Spécifier des contraintes supplémentaires de dimensionnement des widgets
Android 12 ajoute des API qui vous permettent de vous assurer que votre widget est dimensionné de manière plus fiable sur différents appareils avec des tailles d'écran variables.
En plus des attributs minWidth, minHeight, minResizeWidth et minResizeHeight existants, utilisez les nouveaux attributs appwidget-provider suivants :
targetCellWidthettargetCellHeight: définissent la taille cible du widget en termes de cellules de la grille du lanceur d'applications. S'ils sont définis, ces attributs sont utilisés à la place deminWidthouminHeight.maxResizeWidthetmaxResizeHeight: définissent la taille maximale à laquelle le lanceur d'application permet à l'utilisateur de redimensionner le widget.
Le code XML suivant montre comment utiliser les attributs de dimensionnement.
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:targetCellWidth="3" android:targetCellHeight="2" android:maxResizeWidth="250dp" android:maxResizeHeight="110dp"> </appwidget-provider>
Fournir des mises en page responsives
Si la mise en page doit changer en fonction de la taille du widget, nous vous recommandons de créer un petit ensemble de mises en page, chacune étant valide pour une plage de tailles. Si ce n'est pas possible, une autre option consiste à fournir des mises en page basées sur la taille exacte du widget au moment de l'exécution, comme décrit sur cette page.
Cette fonctionnalité permet un scaling plus fluide et une meilleure intégrité globale du système, car le système n'a pas besoin de réactiver l'application chaque fois qu'il affiche le widget dans une taille différente.
L'exemple de code suivant montre comment fournir une liste de mises en page.
override fun onUpdate( /* ... */ ) { val smallView = RemoteViews( /* ... */ ) val tallView = RemoteViews( /* ... */ ) val wideView = RemoteViews( /* ... */ ) val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(150f, 100f) to smallView, SizeF(150f, 200f) to tallView, SizeF(215f, 100f) to wideView ) val remoteViews = RemoteViews(viewMapping) appWidgetManager.updateAppWidget(id, remoteViews) }
Supposons que le widget possède les attributs suivants :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minResizeWidth="160dp" android:minResizeHeight="110dp" android:maxResizeWidth="250dp" android:maxResizeHeight="200dp"> </appwidget-provider>
L'extrait de code précédent signifie ce qui suit :
smallViewaccepte les tailles de 160 dp (minResizeWidth) x 110 dp (minResizeHeight) à 160 dp x 199 dp (point de coupure suivant - 1 dp).tallViewaccepte les dimensions de 160 dp × 200 dp à 214 dp (point de coupure suivant - 1) × 200 dp.wideViewaccepte les tailles de 215 dp × 110 dp (minResizeHeight) à 250 dp (maxResizeWidth) × 200 dp (maxResizeHeight).
Votre widget doit être compatible avec la plage de tailles allant de minResizeWidth × minResizeHeight à maxResizeWidth × maxResizeHeight. Dans cette plage, vous pouvez décider du point de basculement pour changer de mise en page.
Fournir des mises en page exactes
Si un petit ensemble de mises en page responsives n'est pas possible, vous pouvez fournir différentes mises en page adaptées aux tailles d'affichage du widget. En général, il s'agit de deux tailles pour les téléphones (mode Portrait et mode Paysage) et de quatre tailles pour les pliables.
Pour implémenter cette solution, votre application doit effectuer les étapes suivantes :
Surchargez
AppWidgetProvider.onAppWidgetOptionsChanged(), qui est appelé lorsque l'ensemble de tailles change.Appelez
AppWidgetManager.getAppWidgetOptions(), qui renvoie unBundlecontenant les tailles.Accédez à la clé
AppWidgetManager.OPTION_APPWIDGET_SIZESà partir deBundle.
L'exemple de code suivant montre comment fournir des mises en page exactes.
override fun onAppWidgetOptionsChanged( context: Context, appWidgetManager: AppWidgetManager, id: Int, newOptions: Bundle? ) { super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions) // Get the new sizes. val sizes = newOptions?.let { BundleCompat.getParcelableArrayList( it, AppWidgetManager.OPTION_APPWIDGET_SIZES, SizeF::class.java ) } // Check that the list of sizes is provided by the launcher. if (sizes.isNullOrEmpty()) { return } // Map the sizes to the RemoteViews that you want. val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews)) appWidgetManager.updateAppWidget(id, remoteViews) } // Create the RemoteViews for the given size. private fun createRemoteViews(size: SizeF): RemoteViews { }
Déterminer la taille de votre widget
Chaque widget doit définir un targetCellWidth et un targetCellHeight pour les appareils équipés d'Android 12 ou version ultérieure, ou un minWidth et un minHeight pour toutes les versions d'Android, indiquant l'espace minimal qu'il consomme par défaut. Toutefois, lorsque les utilisateurs ajoutent un widget à leur écran d'accueil, celui-ci occupe généralement plus que la largeur et la hauteur minimales que vous spécifiez.
Les écrans d'accueil Android offrent aux utilisateurs une grille d'espaces disponibles sur lesquels ils peuvent placer des widgets et des icônes. Cette grille peut varier selon l'appareil. Par exemple, de nombreux téléphones proposent une grille de 5 x 4, et les tablettes peuvent proposer une grille plus grande. Lorsque votre widget est ajouté, il est étiré pour occuper le nombre minimal de cellules, horizontalement et verticalement, requis pour satisfaire les contraintes de ses attributs targetCellWidth et targetCellHeight sur les appareils équipés d'Android 12 ou version ultérieure, ou les contraintes minWidth et minHeight sur les appareils équipés d'Android 11 (niveau d'API 30) ou version antérieure.
Les dimensions des cellules et les marges automatiques varient selon les appareils. Utilisez le tableau suivant pour estimer les dimensions minimales de votre widget sur un téléphone standard avec une grille de 5 x 4, en fonction du nombre de cellules de grille que vous souhaitez occuper :
| Nombre de cellules (largeur x hauteur) | Taille disponible en mode Portrait (dp) | Taille disponible en mode Paysage (dp) |
|---|---|---|
| 1x1 | 57 x 102 dp | 127 x 51 dp |
| 2x1 | 130 x 102 dp | 269 x 51 dp |
| 3x1 | 203 x 102 dp | 412 x 51 dp |
| 4x1 | 276 x 102 dp | 554 x 51 dp |
| 5x1 | 349 x 102 dp | 697 x 51 dp |
| 5x2 | 349 x 220 dp | 697 x 117 dp |
| 5x3 | 349 x 337 dp | 697 x 184 dp |
| 5x4 | 349 x 455 dp | 697 x 250 dp |
| … | … | … |
| n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
Utilisez les tailles de cellule du mode Portrait pour définir les valeurs que vous fournissez pour les attributs minWidth, minResizeWidth et maxResizeWidth. De même, utilisez les tailles de cellule en mode Paysage pour déterminer les valeurs à fournir pour les attributs minHeight, minResizeHeight et maxResizeHeight.
En effet, la largeur des cellules est généralement plus petite en mode Portrait qu'en mode Paysage. De même, la hauteur des cellules est généralement plus petite en mode Paysage qu'en mode Portrait.
Par exemple, si vous souhaitez que la largeur de votre widget puisse être redimensionnée jusqu'à une cellule sur un Google Pixel 4, vous devez définir votre minResizeWidth sur 56 dp au maximum pour vous assurer que la valeur de l'attribut minResizeWidth est inférieure à 57 dp, car une cellule mesure au moins 57 dp de large en mode portrait.
De même, si vous souhaitez que la hauteur de votre widget soit redimensionnable dans une cellule sur le même appareil, vous devez définir votre minResizeHeight sur 50 dp au maximum pour vous assurer que la valeur de l'attribut minResizeHeight est inférieure à 51 dp, car une cellule mesure au moins 51 dp de haut en mode Paysage.
Chaque widget peut être redimensionné dans les plages de tailles comprises entre les attributs minResizeWidth/minResizeHeight et maxResizeWidth/maxResizeHeight, ce qui signifie qu'il doit s'adapter à toutes les plages de tailles comprises entre ces attributs.
Par exemple, pour définir la taille par défaut du widget lors de l'emplacement, vous pouvez définir les attributs suivants :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:targetCellWidth="3" android:targetCellHeight="2" android:minWidth="180dp" android:minHeight="110dp"> </appwidget-provider>
Cela signifie que la taille par défaut du widget est de 3 x 2 cellules, comme spécifié par les attributs targetCellWidth et targetCellHeight, ou de 180 x 110 dp, comme spécifié par minWidth et minHeight pour les appareils équipés d'Android 11 ou version antérieure. Dans ce dernier cas, la taille en cellules peut varier en fonction de l'appareil.
Pour définir les plages de tailles acceptées de votre widget, vous pouvez également définir les attributs suivants :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minResizeWidth="180dp" android:minResizeHeight="110dp" android:maxResizeWidth="530dp" android:maxResizeHeight="450dp"> </appwidget-provider>
Comme spécifié par les attributs précédents, la largeur du widget peut être redimensionnée de 180 dp à 530 dp, et sa hauteur de 110 dp à 450 dp. Le widget peut ensuite être redimensionné de 3x2 à 5x2 cellules, à condition que les conditions suivantes soient remplies :
- L'appareil dispose de la grille 5x4.
- La correspondance entre le nombre de cellules et la taille disponible en dp suit le tableau d'estimation des dimensions minimales de cette page.
- Le widget s'adapte à cette plage de tailles.
val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small) val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium) val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large) val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(180f, 110f) to smallView, SizeF(270f, 110f) to mediumView, SizeF(270f, 280f) to largeView ) appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))
Supposons que le widget utilise les mises en page responsives définies dans les extraits de code précédents. Cela signifie que la mise en page spécifiée comme R.layout.widget_weather_forecast_small est utilisée de 180 dp (minResizeWidth) x 110 dp (minResizeHeight) à 269 x 279 dp (points de coupure suivants - 1). De même, R.layout.widget_weather_forecast_medium est utilisé de 270 x 110 dp à 270 x 279 dp, et R.layout.widget_weather_forecast_large est utilisé de 270 x 280 dp à 530 dp (maxResizeWidth) x 450 dp (maxResizeHeight).
Lorsque l'utilisateur redimensionne le widget, son apparence change pour s'adapter à chaque taille en cellules, comme illustré dans les exemples suivants.
R.layout.widget_weather_forecast_small.
R.layout.widget_weather_forecast_medium.
R.layout.widget_weather_forecast_medium.
R.layout.widget_weather_forecast_large.
R.layout.widget_weather_forecast_large.