In questa pagina vengono descritti i perfezionamenti per le dimensioni dei widget e una maggiore flessibilità introdotti in Android 12 (livello API 31). Inoltre, spiega come determinare le dimensioni del widget.
Utilizza API migliorate per le dimensioni e i layout dei widget
A partire da Android 12 (livello API 31), puoi fornire attributi delle dimensioni più raffinati e layout flessibili seguendo questa procedura, come descritto nelle sezioni che seguono:
Fornire layout adattabili o layout esatti.
Nelle versioni precedenti di Android, è possibile ottenere gli intervalli di dimensioni di un
widget utilizzando gli 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 destinati ad Android 12 o versioni successive, consigliamo di fornire layout adattabili o esatti.
Specifica vincoli aggiuntivi relativi alle dimensioni dei widget
Android 12 aggiunge API che ti consentono di garantire che le dimensioni del widget siano più affidabili su diversi dispositivi con schermi di varie dimensioni.
Oltre agli attributi esistenti minWidth
,
minHeight
,
minResizeWidth
,
e minResizeHeight
, utilizza i seguenti nuovi attributi appwidget-provider
:
targetCellWidth
etargetCellHeight
: definisci le dimensioni di destinazione del widget in termini di celle della griglia Avvio app. Se definiti, questi attributi vengono utilizzati al posto diminWidth
ominHeight
.maxResizeWidth
emaxResizeHeight
: definisci le dimensioni massime a cui l'Avvio app consente all'utente di ridimensionare il widget.
Il seguente XML mostra come utilizzare gli attributi di dimensionamento.
<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 non è possibile, un'altra opzione è fornire layout in base alle dimensioni esatte del widget in fase di esecuzione, come descritto in questa pagina.
Questa funzionalità consente una scalabilità più fluida e un migliore stato generale del sistema, poiché il sistema non deve riattivare l'app ogni volta che mostra il widget in dimensioni diverse.
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); }
Supponiamo 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 indica quanto segue:
smallView
supporta da 160 dp (minResizeWidth
) × 110 dp (minResizeHeight
) a 160 dp × 199 dp (punto di taglio successivo - 1 dp).tallView
supporta da 160 dp × 200 dp a 214 dp (punto di taglio 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 di questo intervallo,
puoi decidere il punto di taglio per cambiare layout.
Fornisci layout esatti
Se non è possibile realizzare un piccolo insieme di layout adattabili, puoi comunque fornire layout diversi in base alle dimensioni in cui viene mostrato il widget. Di solito si tratta di due dimensioni per gli smartphone (modalità verticale e orizzontale) e quattro per i dispositivi pieghevoli.
Per implementare questa soluzione, la tua app deve eseguire i seguenti passaggi:
Overload
AppWidgetProvider.onAppWidgetOptionsChanged()
, che viene chiamato quando cambia l'insieme di dimensioni.Chiama
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) { }
Determina una dimensione per il widget
Ogni widget deve definire un targetCellWidth
e un targetCellHeight
per i dispositivi con Android 12 o versioni successive oppure minWidth
e minHeight
per tutte le versioni di Android, indicando la quantità minima di spazio che occupa per impostazione predefinita. Tuttavia, quando gli utenti aggiungono un widget alla schermata Home, in genere questo occupa più della larghezza e dell'altezza minime specificate.
Le schermate Home di Android offrono agli utenti una griglia di spazi disponibili in cui possono
posizionare widget e icone. Questa griglia può variare in base al dispositivo. Ad esempio, molti smartphone offrono una griglia 5 x 4, mentre i tablet possono offrire una griglia più grande. Quando il widget viene aggiunto, viene allungato per occupare il numero minimo di celle, orizzontalmente e verticalmente, necessarie per soddisfare i vincoli per targetCellWidth
e targetCellHeight
sui dispositivi con Android 12 o versioni successive oppure i vincoli per minWidth
e minHeight
sui dispositivi con Android 11 (livello API 30) o versioni precedenti.
Sia la larghezza che l'altezza di una cella e le dimensioni dei margini automatici applicati ai widget possono variare in base al dispositivo. Utilizza la seguente tabella per stimare approssimativamente le dimensioni minime del widget in un tipico smartphone con griglia 5x4, in base al numero di celle della griglia che vuoi occupare:
Numero di celle (larghezza x altezza) | Dimensioni disponibili in modalità Ritratto (dp) | Dimensioni disponibili in modalità Orizzontale (dp) |
---|---|---|
1x1 | 57 x 102 dp | 127 x 51 dp |
2x1 | 130x102dp | 269 x 51 dp |
3x1 | 203 x 102 dp | 412x51dp |
4x1 | 276 x 102 dp | 554 x 51 dp |
5 x 1 | 349x102dp | 697 x 51 dp |
5x2 | 349x220dp | 697x117dp |
5x3 | 349x337dp | 697 x 184 dp |
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 definire i valori che fornisci per
gli attributi minWidth
, minResizeWidth
e maxResizeWidth
. Analogamente,
utilizza le dimensioni delle celle in modalità Orizzontale per specificare i valori forniti
per gli attributi minHeight
, minResizeHeight
e maxResizeHeight
.
Il motivo è che la larghezza della cella è in genere più piccola in modalità Ritratto che in modalità Orizzontale e, analogamente, l'altezza della cella è in genere più piccola in modalità Orizzontale che in modalità Ritratto.
Ad esempio, se vuoi che la larghezza del widget sia ridimensionabile fino a una cella su Google Pixel 4, devi impostare minResizeWidth
su massimo 56 dp per assicurarti che il valore dell'attributo minResizeWidth
sia inferiore a 57 dp, perché una cella è larga almeno 57 dp in modalità Ritratto.
Analogamente, se vuoi che l'altezza del widget sia ridimensionabile in una cella sullo stesso dispositivo, devi impostare minResizeHeight
su massimo 50 dp per assicurarti che il valore dell'attributo minResizeHeight
sia inferiore a 51 dp, perché una cella è alta almeno 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 compreso tra questi.
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 le dimensioni predefinite del widget sono celle 3 x 2, come specificato dagli attributi targetCellWidth
e targetCellHeight
, oppure 180 x 110 dp, come specificato da minWidth
e minHeight
per i dispositivi con Android 11 o versioni precedenti. In quest'ultimo caso, le dimensioni nelle celle possono variare in base al dispositivo.
Inoltre, per impostare gli intervalli di dimensioni supportati dal 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 la sua altezza è ridimensionabile da 110 dp a 450 dp. Il widget può quindi essere ridimensionato da celle 3x2 a 5x2, a condizione che siano presenti le seguenti condizioni:
- Il dispositivo ha una griglia 5x4.
- La mappatura tra il numero di celle e le dimensioni disponibili in dpi segue la tabella che mostra la stima delle dimensioni minime in questa pagina.
- Il widget si adatta a questo 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, mentreR.layout.widget_weather_forecast_large
viene utilizzato da 270 x 280 dp a
530 dp (maxResizeWidth
) x 450 dp (maxResizeHeight
).
Quando l'utente modifica le dimensioni del widget, il suo aspetto cambia per adattarsi a ogni dimensione delle celle, come mostrato negli esempi seguenti.