Na tej stronie opisujemy ulepszenia dotyczące rozmiarów widżetów i większej elastyczności wprowadzone w Androidzie 12 (API na poziomie 31). Znajdziesz w nim też informacje o tym, jak określić rozmiar widżetu.
Korzystanie z ulepszonych interfejsów API do określania rozmiarów i układów widżetów
Od Androida 12 (API na poziomie 31) możesz podawać bardziej precyzyjne atrybuty rozmiaru i elastyczne układy, wykonując te czynności (opisane w dalszych sekcjach):
zapewniać elastyczne układy stron lub dokładne układy stron;
W poprzednich wersjach Androida można było uzyskać zakresy rozmiarów widżetu za pomocą dodatków OPTION_APPWIDGET_MIN_WIDTH
, OPTION_APPWIDGET_MIN_HEIGHT
, OPTION_APPWIDGET_MAX_WIDTH
i OPTION_APPWIDGET_MAX_HEIGHT
, a następnie oszacować rozmiar widżetu, ale ta logika nie działa we wszystkich sytuacjach. W przypadku widżetów kierowanych na Androida 12 lub nowszego zalecamy udostępnianie elastycznych lub dokładnych układów.
Określanie dodatkowych ograniczeń rozmiaru widżetu
Android 12 dodaje interfejsy API, które pozwalają zapewnić bardziej niezawodne określanie rozmiaru widżetu na różnych urządzeniach o różnych rozmiarach ekranu.
Oprócz dotychczasowych atrybutów minWidth
, minHeight
, minResizeWidth
i minResizeHeight
użyj tych nowych atrybutów appwidget-provider
:
targetCellWidth
itargetCellHeight
: określają docelowy rozmiar widżetu w komórkach siatki programu uruchamiającego. Jeśli są zdefiniowane, te atrybuty są używane zamiastminWidth
lubminHeight
.maxResizeWidth
imaxResizeHeight
określają maksymalny rozmiar, do którego użytkownik może zmienić rozmiar widżetu.
Poniższy kod XML pokazuje, jak używać atrybutów rozmiaru.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
Zapewnianie elastycznych układów
Jeśli układ musi się zmieniać w zależności od rozmiaru widżetu, zalecamy utworzenie niewielkiego zestawu układów, z których każdy będzie odpowiedni dla określonego zakresu rozmiarów. Jeśli to nie jest możliwe, możesz też udostępniać układy na podstawie dokładnego rozmiaru widżetu w czasie działania, jak opisano na tej stronie.
Ta funkcja umożliwia płynniejsze skalowanie i ogólnie lepsze działanie systemu, ponieważ nie musi on budzić aplikacji za każdym razem, gdy wyświetla widżet w innym rozmiarze.
Poniższy przykład kodu pokazuje, jak podać listę układów.
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); }
Załóżmy, że widżet ma te atrybuty:
<appwidget-provider
android:minResizeWidth="160dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="250dp"
android:maxResizeHeight="200dp">
</appwidget-provider>
Powyższy fragment kodu oznacza:
smallView
obsługuje rozmiary od 160 dp (minResizeWidth
) × 110 dp (minResizeHeight
) do 160 dp × 199 dp (następny punkt odcięcia – 1 dp).tallView
obsługuje rozmiary od 160 dp × 200 dp do 214 dp (następny punkt odcięcia – 1) × 200 dp.wideView
obsługuje rozmiary od 215 dp × 110 dp (minResizeHeight
) do 250 dp (maxResizeWidth
) × 200 dp (maxResizeHeight
).
Widżet musi obsługiwać zakres rozmiarów od minResizeWidth
× minResizeHeight
do maxResizeWidth
× maxResizeHeight
. W tym zakresie możesz określić punkt odcięcia, w którym nastąpi zmiana układu.

Podawanie dokładnych układów
Jeśli mały zestaw układów elastycznych nie jest możliwy, możesz zamiast tego podać różne układy dostosowane do rozmiarów, w których wyświetlany jest widżet. Zwykle są to 2 rozmiary w przypadku telefonów (tryb pionowy i poziomy) oraz 4 rozmiary w przypadku urządzeń składanych.
Aby wdrożyć to rozwiązanie, aplikacja musi wykonać te czynności:
Przeciąż metodę
AppWidgetProvider.onAppWidgetOptionsChanged()
, która jest wywoływana, gdy zmienia się zestaw rozmiarów.Wywołaj funkcję
AppWidgetManager.getAppWidgetOptions()
, która zwracaBundle
zawierający rozmiary.Uzyskaj dostęp do klucza
AppWidgetManager.OPTION_APPWIDGET_SIZES
z poziomuBundle
.
Poniższy przykład kodu pokazuje, jak podać dokładne układy.
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) { }
Określanie rozmiaru widżetu
Każdy widżet musi definiować targetCellWidth
i targetCellHeight
w przypadku urządzeń z Androidem 12 lub nowszym albo minWidth
i minHeight
w przypadku wszystkich wersji Androida, wskazując minimalną ilość miejsca, jaką zajmuje domyślnie. Gdy jednak użytkownicy dodają widżet do ekranu głównego, zajmuje on zwykle więcej miejsca niż minimalna szerokość i wysokość, które określisz.
Ekran główny Androida to siatka dostępnych miejsc, w których użytkownicy mogą umieszczać widżety i ikony. Ta siatka może się różnić w zależności od urządzenia. Na przykład wiele telefonów komórkowych ma siatkę 5x4, a tablety mogą mieć większą siatkę. Gdy widżet zostanie dodany, zostanie rozciągnięty, aby zajmować minimalną liczbę komórek w pionie i poziomie wymaganą do spełnienia ograniczeń dotyczących jego targetCellWidth
i targetCellHeight
na urządzeniach z Androidem 12 lub nowszym albo ograniczeń minWidth
i minHeight
na urządzeniach z Androidem 11 (poziom API 30) lub starszym.
Zarówno szerokość, jak i wysokość komórki oraz rozmiar automatycznych marginesów stosowanych do widżetów mogą się różnić w zależności od urządzenia. Skorzystaj z tabeli poniżej, aby w przybliżeniu oszacować minimalne wymiary widżetu na typowym telefonie z siatką 5x4, biorąc pod uwagę liczbę zajętych komórek siatki:
Liczba komórek (szerokość x wysokość) | Dostępny rozmiar w trybie portretowym (dp) | Dostępny rozmiar w trybie poziomym (dp) |
---|---|---|
1x1 | 57 x 102 dp | 127x51dp |
2x1 | 130x102dp | 269x51dp |
3:1 | 203x102dp | 412x51dp |
4:1 | 276 x 102 dp | 554 x 51 dp |
5:1 | 349 x 102 dp | 697x51dp |
5x2 | 349 x 220 dp | 697 x 117 dp |
5x3 | 349x337dp | 697 x 184 dp |
5x4 | 349x455dp | 697 x 250 dp |
… | ... | … |
n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
Użyj rozmiarów komórek w trybie portretowym, aby określić wartości atrybutów minWidth
, minResizeWidth
i maxResizeWidth
. Podobnie w przypadku atrybutów minHeight
, minResizeHeight
i maxResizeHeight
podawaj wartości na podstawie rozmiarów komórek w trybie poziomym.
Dzieje się tak, ponieważ szerokość komórki jest zwykle mniejsza w trybie pionowym niż w poziomym, a wysokość komórki jest zwykle mniejsza w trybie poziomym niż w pionowym.
Jeśli na przykład chcesz, aby szerokość widżetu można było zmniejszyć do 1 komórki na Google Pixelu 4, musisz ustawić wartość minResizeWidth
na co najwyżej 56 dp, aby wartość atrybutu minResizeWidth
była mniejsza niż 57 dp, ponieważ komórka w trybie pionowym ma co najmniej 57 dp szerokości.
Podobnie, jeśli chcesz, aby wysokość widżetu w jednej komórce na tym samym urządzeniu można było zmieniać, musisz ustawić wartość minResizeHeight
na co najwyżej 50 dp, aby wartość atrybutu minResizeHeight
była mniejsza niż 51 dp, ponieważ jedna komórka ma co najmniej 51 dp wysokości w trybie poziomym.
Każdy widżet można zmieniać w zakresach rozmiarów określonych przez atrybuty minResizeWidth
/minResizeHeight
i maxResizeWidth
/maxResizeHeight
, co oznacza, że musi się on dostosowywać do wszystkich zakresów rozmiarów między nimi.
Aby na przykład ustawić domyślny rozmiar widżetu w miejscu docelowym, możesz skonfigurować te atrybuty:
<appwidget-provider
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
Oznacza to, że domyślny rozmiar widżetu to 3x2 komórki, zgodnie z atrybutami
targetCellWidth
i targetCellHeight
, lub 180×110 dp, zgodnie z atrybutami minWidth
i minHeight
w przypadku urządzeń z Androidem 11 lub starszym. W tym drugim przypadku rozmiar w komórkach może się różnić w zależności od urządzenia.
Aby ustawić obsługiwane zakresy rozmiarów widżetu, możesz też określić te atrybuty:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
Zgodnie z atrybutami podanymi powyżej szerokość widżetu można zmieniać w zakresie od 180 dp do 530 dp, a wysokość – od 110 dp do 450 dp. Rozmiar widżetu można zmienić z 3x2 na 5x2 komórki, o ile spełnione są te warunki:
- Urządzenie ma siatkę 5x4.
- Mapowanie między liczbą komórek a dostępnym rozmiarem w dps jest zgodne z tabelą pokazującą szacunkowe minimalne wymiary na tej stronie.
- Widżet dostosuje się do tego zakresu rozmiarów.
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);
Załóżmy, że widżet korzysta z układów elastycznych zdefiniowanych we wcześniejszych fragmentach kodu. Oznacza to, że układ określony jako
R.layout.widget_weather_forecast_small
jest używany w zakresie od 180 dp (minResizeWidth
) x 110 dp (minResizeHeight
) do 269 x 279 dp (następne punkty odcięcia – 1). Podobnie symbol
R.layout.widget_weather_forecast_medium
jest używany w przypadku rozmiarów od 270 x 110 dp do 270 x 279 dp, a symbol R.layout.widget_weather_forecast_large
– w przypadku rozmiarów od 270 x 280 dp do 530 dp (maxResizeWidth
) x 450 dp (maxResizeHeight
).
Gdy użytkownik zmienia rozmiar widżetu, jego wygląd dostosowuje się do każdego rozmiaru w komórkach, jak pokazano w przykładach poniżej.

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
.