Questa pagina descrive i perfezionamenti per il dimensionamento dei widget e la maggiore flessibilità introdotti in Android 12 (livello API 31). Descrive inoltre come determinare le dimensioni del widget.
Usa API migliorate per dimensioni e layout dei widget
A partire da Android 12 (livello API 31), puoi fornire attributi relativi alle dimensioni più perfezionati e layout flessibili procedendo nel seguente modo, come descritto nelle sezioni riportate di seguito:
Forniscono layout adattabili o layout esatti.
Nelle versioni precedenti di Android, è possibile ottenere gli intervalli di dimensioni di un
widget utilizzando gli elementi extra
OPTION_APPWIDGET_MIN_WIDTH
,
OPTION_APPWIDGET_MIN_HEIGHT
,
OPTION_APPWIDGET_MAX_WIDTH
e OPTION_APPWIDGET_MAX_HEIGHT
e quindi stimare le dimensioni del widget, ma questa logica non funziona in tutte
le situazioni. Per i widget che hanno come target Android 12 o versioni successive, consigliamo di
fornire layout reattivi o esatti.
Specifica vincoli di dimensione del widget aggiuntivi
Android 12 aggiunge API per garantire che il widget venga dimensionato in modo più affidabile su dispositivi diversi con schermi di varie dimensioni.
Oltre agli attributi minWidth
,
minHeight
,
minResizeWidth
e minResizeHeight
esistenti, utilizza i seguenti nuovi attributi appwidget-provider
:
targetCellWidth
etargetCellHeight
: definiscono le dimensioni di destinazione del widget in termini di celle della griglia di Avvio app. Se definiti, questi attributi vengono utilizzati al posto diminWidth
ominHeight
.maxResizeWidth
emaxResizeHeight
: definiscono la dimensione massima che Avvio app consente all'utente di ridimensionare il widget.
Il seguente XML mostra come utilizzare gli attributi relativi alle dimensioni.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
Fornisci layout adattabili
Se il layout deve cambiare a seconda delle dimensioni del widget, ti consigliamo di creare un piccolo insieme di layout, ciascuno valido per una serie di dimensioni. Se ciò non è possibile, un'altra opzione è fornire layout basati sulle dimensioni esatte del widget in fase di runtime, come descritto in questa pagina.
Questa funzionalità consente una scalabilità più fluida e una migliore integrità del sistema, in quanto il sistema non deve attivare l'app ogni volta che mostra il widget in una dimensione diversa.
Il seguente esempio di codice mostra come fornire un elenco di layout.
Kotlin
override fun onUpdate(...) { val smallView = ... val tallView = ... val wideView = ... 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) }
Java
@Override public void onUpdate(...) { RemoteViews smallView = ...; RemoteViews tallView = ...; RemoteViews wideView = ...; Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(150f, 100f), smallView); viewMapping.put(new SizeF(150f, 200f), tallView); viewMapping.put(new SizeF(215f, 100f), wideView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); }
Supponi che il widget abbia i seguenti attributi:
<appwidget-provider
android:minResizeWidth="160dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="250dp"
android:maxResizeHeight="200dp">
</appwidget-provider>
Lo snippet di codice precedente significa quanto segue:
smallView
supporta da 160 dp (minResizeWidth
) × 110 dp (minResizeHeight
) a 160 dp × 199 dp (punto di interruzione successivo - 1 dp).tallView
supporta da 160 dp × 200 dp a 214 dp (punto di interruzione successivo - 1) × 200 dp.wideView
supporta da 215 dp × 110 dp (minResizeHeight
) a 250 dp (maxResizeWidth
) × 200 dp (maxResizeHeight
).
Il widget deve supportare l'intervallo di dimensioni compreso tra minResizeWidth
×
minResizeHeight
e maxResizeWidth
× maxResizeHeight
. All'interno dell'intervallo, puoi decidere il punto limite
per cambiare layout.
![Esempio di layout adattabile](https://developer.android.com/static/images/appwidgets/size-range.gif?authuser=8&hl=it)
Fornisci layout esatti
Se non è possibile realizzare un piccolo insieme di layout adattabili, puoi fornire diversi layout personalizzati per le dimensioni di visualizzazione del widget. In genere, sono di due dimensioni per gli smartphone (modalità verticale e orizzontale) e quattro per i dispositivi pieghevoli.
Per implementare questa soluzione, la tua app deve svolgere i seguenti passaggi:
Sovraccarico
AppWidgetProvider.onAppWidgetOptionsChanged()
, che viene chiamato quando l'insieme di dimensioni cambia.Richiama
AppWidgetManager.getAppWidgetOptions()
, che restituisce unBundle
contenente le dimensioni.Accedi alla chiave
AppWidgetManager.OPTION_APPWIDGET_SIZES
daBundle
.
Il seguente esempio di codice mostra come fornire layout esatti.
Kotlin
override fun onAppWidgetOptionsChanged( context: Context, appWidgetManager: AppWidgetManager, id: Int, newOptions: Bundle? ) { super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions) // Get the new sizes. val sizes = newOptions?.getParcelableArrayList<SizeF>( AppWidgetManager.OPTION_APPWIDGET_SIZES ) // 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 { }
Java
@Override public void onAppWidgetOptionsChanged( Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); // Get the new sizes. ArrayList<SizeF> sizes = newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES); // Check that the list of sizes is provided by the launcher. if (sizes == null || sizes.isEmpty()) { return; } // Map the sizes to the RemoteViews that you want. Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); for (SizeF size : sizes) { viewMapping.put(size, createRemoteViews(size)); } RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); } // Create the RemoteViews for the given size. private RemoteViews createRemoteViews(SizeF size) { }
Determinare le dimensioni del widget
Ogni widget deve definire un valore targetCellWidth
e un targetCellHeight
per i dispositivi
con Android 12 o versioni successive oppure minWidth
e minHeight
per tutte
le versioni di Android, a indicare la quantità minima di spazio che utilizza
per impostazione predefinita. Tuttavia, quando gli utenti aggiungono un widget alla schermata Home, di solito quest'ultimo occupa più dell'altezza e della larghezza minime specificate.
Le schermate Home di Android offrono agli utenti una griglia di spazi disponibili su cui posizionare widget e icone. Questa griglia può variare in base al dispositivo; ad esempio, molti smartphone hanno una griglia 5:4, mentre i tablet hanno una griglia più grande. Quando il widget viene aggiunto, viene allungato per occupare il numero minimo di celle, orizzontalmente e verticalmente, necessario per soddisfare i vincoli relativi a targetCellWidth
e targetCellHeight
sui dispositivi con Android 12 o versioni successive oppure ai vincoli minWidth
e minHeight
sui dispositivi con Android 11 (livello API 30) o versioni precedenti.
Sia la larghezza e l'altezza di una cella sia le dimensioni dei margini automatici applicati ai widget possono variare da un dispositivo all'altro. Utilizza la seguente tabella per stimare approssimativamente le dimensioni minime del widget in un tipico dispositivo con griglia 5 x 4, dato il numero di celle della griglia occupate che vuoi:
Numero di celle (larghezza x altezza) | Dimensioni disponibili in modalità verticale (dp) | Dimensioni disponibili in modalità Orizzontale (dp) |
---|---|---|
1x1 | 57x102dp | 127x51dp |
2x1 | 130x102dp | 269x51dp |
3x1 | 203x102dp | 412x51dp |
4x1 | 276x102dp | 554x51dp |
5x1 | 349x102dp | 697x51dp |
5x2 | 349x220dp | 697x117dp |
5x3 | 349x337dp | 697x184dp |
5x4 | 349x455dp | 697x250dp |
… | ... | … |
n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
Utilizza le dimensioni delle celle in modalità verticale per stabilire i valori forniti per gli
attributi minWidth
, minResizeWidth
e maxResizeWidth
. Analogamente,
utilizza le dimensioni delle celle in modalità Orizzontale per definire i valori che fornisci
per gli attributi minHeight
, minResizeHeight
e maxResizeHeight
.
Il motivo è che la larghezza della cella è generalmente inferiore in modalità verticale che in modalità Orizzontale e, analogamente, l'altezza della cella è generalmente più piccola in modalità Orizzontale rispetto alla modalità Ritratto.
Ad esempio, se vuoi che la larghezza del widget sia ridimensionabile a una cella su Google Pixel 4, devi impostare minResizeWidth
su un massimo di 56 dp per assicurarti che il valore dell'attributo minResizeWidth
sia inferiore a 57 dp, poiché una cella ha una larghezza minima di 57 dp in verticale.
Analogamente, se vuoi che l'altezza del widget sia ridimensionabile in una cella dello stesso dispositivo, devi impostare minResizeHeight
su un massimo di 50 dp per assicurarti che il valore dell'attributo minResizeHeight
sia inferiore a 51 dp, poiché una cella ha un'altezza minima di 51 dp in modalità Orizzontale.
Ogni widget è ridimensionabile all'interno degli intervalli di dimensioni compresi tra gli attributi minResizeWidth
/minResizeHeight
e maxResizeWidth
/maxResizeHeight
, il che significa che deve adattarsi a qualsiasi intervallo di dimensioni tra loro.
Ad esempio, per impostare le dimensioni predefinite del widget nel posizionamento, puoi impostare i seguenti attributi:
<appwidget-provider
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
Ciò significa che la dimensione predefinita del widget è 3 x 2 celle, come specificato dagli attributi targetCellWidth
e targetCellHeight
, o 180 × 110 dp, come specificato da minWidth
e minHeight
per i dispositivi con Android 11 o versioni precedenti. Nel secondo caso, le dimensioni delle celle
variano in base al dispositivo.
Inoltre, per impostare gli intervalli di dimensioni supportati per il widget, puoi impostare i seguenti attributi:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
Come specificato dagli attributi precedenti, la larghezza del widget è ridimensionabile da 180 dp a 530 dp e l'altezza da 110 dp a 450 dp. Il widget è quindi ridimensionabile da 3 x 2 a 5 x 2 celle, a condizione che siano presenti le seguenti condizioni:
- Il dispositivo ha una griglia 5 x 4.
- La mappatura tra il numero di celle e le dimensioni disponibili in dps segue la tabella che mostra la stima delle dimensioni minime in questa pagina.
- Il widget si adatta a quell'intervallo di dimensioni.
Kotlin
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))
Java
RemoteViews smallView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small); RemoteViews mediumView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium); RemoteViews largeView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large); Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(180f, 110f), smallView); viewMapping.put(new SizeF(270f, 110f), mediumView); viewMapping.put(new SizeF(270f, 280f), largeView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews);
Supponiamo che il widget utilizzi i layout adattabili definiti negli
snippet di codice precedenti. Ciò significa che il layout specificato come R.layout.widget_weather_forecast_small
viene utilizzato da 180 dp (minResizeWidth
) x 110 dp (minResizeHeight
) a 269 x 279 dp (punti di interruzione successivi - 1). Analogamente,
R.layout.widget_weather_forecast_medium
viene utilizzato da 270 x 110 dp a 270 x 279 dp
e R.layout.widget_weather_forecast_large
viene utilizzato da 270 x 280 dp a
530 dp (maxResizeWidth
) x 450 dp (maxResizeHeight
).
Quando l'utente ridimensiona il widget, il suo aspetto cambia in base alle dimensioni delle celle, come mostrato negli esempi seguenti.
![Esempio di widget meteo nella dimensione più piccola della griglia 3x2. L'interfaccia utente mostra il nome della località (Tokyo), la temperatura (14°) e il simbolo che indica tempo parzialmente nuvoloso.](https://developer.android.com/static/images/appwidgets/weather-size-3x2.png?authuser=8&hl=it)
R.layout.widget_weather_forecast_small
3 x 2.![Esempio di widget meteo in formato "medio" 4 x 2. Il ridimensionamento del widget in questo modo si basa su tutta l'interfaccia utente rispetto alla dimensione precedente del widget e aggiunge l'etichetta "Molto nuvoloso" e una previsione delle temperature tra le 16:00 e le 19:00.](https://developer.android.com/static/images/appwidgets/weather-size-4x2.png?authuser=8&hl=it)
R.layout.widget_weather_forecast_medium
4:2.![Esempio di widget meteo in formato "medio" 5 x 2. Se il widget viene ridimensionato in questo modo, l'interfaccia utente viene visualizzata come la dimensione precedente, ad eccezione del fatto che viene allungato di una cella per occupare più spazio orizzontale.](https://developer.android.com/static/images/appwidgets/weather-size-5x2.png?authuser=8&hl=it)
R.layout.widget_weather_forecast_medium
.![Esempio di widget meteo in formato "grande" 5 x 3. Il ridimensionamento del widget in questo modo si basa su tutta l'interfaccia utente rispetto alle dimensioni precedenti dei widget e viene aggiunta una visualizzazione all'interno del widget contenente una previsione del meteo di martedì e mercoledì. Simboli che indicano tempo soleggiato o piovoso e temperature elevate e basse per ogni giorno.](https://developer.android.com/static/images/appwidgets/weather-size-5x3.png?authuser=8&hl=it)
R.layout.widget_weather_forecast_large
.![Esempio di widget meteo in formato "large" 5 x 4. Il ridimensionamento del widget in questo modo si basa su tutta l'interfaccia utente rispetto alle dimensioni dei widget precedenti e viene aggiunto giovedì e venerdì (e i simboli corrispondenti che indicano il tipo di tempo, nonché la temperatura massima e minima per ogni giorno).](https://developer.android.com/static/images/appwidgets/weather-size-5x4.png?authuser=8&hl=it)
R.layout.widget_weather_forecast_large
.