Na tej stronie opisano ulepszenia dotyczące rozmiaru widżetów i większej elastyczności wprowadzone w Androidzie 12 (poziom API 31). Znajdziesz w nim też instrukcje określania rozmiaru widżetu.
Używaj ulepszonych interfejsów API do określania rozmiarów i układów widżetów.
Począwszy od Androida 12 (poziom interfejsu API 31), możesz udostępniać bardziej precyzyjne atrybuty rozmiaru i elastyczne układy, wykonując te czynności opisane w poniższych sekcjach:
udostępnianie elastycznych układów lub dokładnych układów;
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 stosowanie elastycznych lub dokładnych układów.
Określanie dodatkowych ograniczeń dotyczących rozmiaru widżetu
Android 12 dodaje interfejsy API, które pozwalają zapewnić bardziej niezawodne dopasowanie rozmiaru widżetu na różnych urządzeniach o różnych rozmiarach ekranu.
Oprócz dotychczasowych atrybutów minWidth, minHeight, minResizeWidth i minResizeHeight używaj tych nowych atrybutów appwidget-provider:
targetCellWidthitargetCellHeight: określają docelowy rozmiar widżetu w komórkach siatki programu uruchamiającego. Jeśli są zdefiniowane, te atrybuty są używane zamiastminWidthlubminHeight.maxResizeWidthimaxResizeHeight: 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 xmlns:android="http://schemas.android.com/apk/res/android" android:targetCellWidth="3" android:targetCellHeight="2" android:maxResizeWidth="250dp" android:maxResizeHeight="110dp"> </appwidget-provider>
Zapewnianie elastycznych układów stron
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 nie jest to możliwe, możesz też udostępnić 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 wybudzać aplikacji za każdym razem, gdy wyświetla widżet w innym rozmiarze.
Poniższy przykładowy kod pokazuje, jak podać listę układów.
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) }
Załóżmy, że widżet ma te atrybuty:
<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>
Powyższy fragment kodu oznacza, że:
smallViewobsługuje od 160 dp (minResizeWidth) × 110 dp (minResizeHeight) do 160 dp × 199 dp (następny punkt odcięcia – 1 dp).tallViewobsługuje od 160 dp × 200 dp do 214 dp (następny punkt odcięcia – 1) × 200 dp.wideViewobsługuje 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.
Podaj dokładne układy.
Jeśli nie możesz utworzyć niewielkiego zestawu układów elastycznych, możesz zamiast tego udostępnić różne układy dostosowane do rozmiarów, w jakich 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ążenie
AppWidgetProvider.onAppWidgetOptionsChanged(), które jest wywoływane, gdy zmienia się zestaw rozmiarów.Wywołaj metodę
AppWidgetManager.getAppWidgetOptions(), która zwraca obiektBundlezawierający rozmiary.Uzyskaj dostęp do klucza
AppWidgetManager.OPTION_APPWIDGET_SIZESzBundle.
Poniższy przykładowy kod pokazuje, jak podać dokładne układy.
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 { }
Określanie rozmiaru widżetu
Każdy widżet musi definiować targetCellWidth i targetCellHeight dla urządzeń z Androidem 12 lub nowszym albo minWidth i minHeight dla wszystkich wersji Androida, wskazując minimalną ilość miejsca, którą domyślnie zajmuje. Jednak gdy użytkownicy dodają widżet do ekranu głównego, zwykle zajmuje on więcej miejsca niż określona przez Ciebie minimalna szerokość i wysokość.
Ekrany główne Androida oferują użytkownikom siatkę dostępnych miejsc, w których mogą umieszczać widżety i ikony. Siatka może się różnić w zależności od urządzenia. Na przykład wiele telefonów ma siatkę 5 x 4, a tablety mogą mieć większą siatkę. Po dodaniu widżet jest rozciągany tak, aby zajmował minimalną liczbę komórek w poziomie i pionie, która jest wymagana do spełnienia ograniczeń targetCellWidth i targetCellHeight na urządzeniach z Androidem 12 lub nowszym albo ograniczeń minWidth i minHeight na urządzeniach z Androidem 11 (API na poziomie 30) lub starszym.
Wymiary komórek i automatyczne marginesy różnią się w zależności od urządzenia. Użyj tej tabeli, aby oszacować minimalne wymiary widżetu na typowym telefonie z siatką 5 x 4, 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) |
|---|---|---|
| 1 x 1 | 57 x 102 dp | 127 x 51 dp |
| 2 x 1 | 130 x 102 dp | 269 x 51 dp |
| 3 × 1 | 203 x 102 dp | 412 x 51 dp |
| 4 × 1 | 276 x 102 dp | 554 x 51 dp |
| 5:1 | 349 x 102 dp | 697 × 51 dp |
| 5 x 2 | 349 x 220 dp | 697 × 117 dp |
| 5 × 3 | 349 x 337 dp | 697 x 184 dp |
| 5 × 4 | 349 x 455 dp | 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 użyj rozmiarów komórek w trybie poziomym, aby określić wartości atrybutów minHeight, minResizeHeight i maxResizeHeight.
Wynika to z tego, że szerokość komórki jest zwykle mniejsza w trybie portretowym niż w trybie poziomym, a wysokość komórki jest zwykle mniejsza w trybie poziomym niż w trybie portretowym.
Jeśli na przykład chcesz, aby szerokość widżetu można było zmniejszyć do 1 komórki na telefonie Google Pixel 4, musisz ustawić wartość minResizeWidth na maksymalnie 56 dp, aby wartość atrybutu minResizeWidth była mniejsza niż 57 dp, ponieważ komórka w orientacji pionowej ma szerokość co najmniej 57 dp.
Podobnie, jeśli chcesz, aby wysokość widżetu można było zmieniać w obrębie jednej komórki na tym samym urządzeniu, musisz ustawić minResizeHeight na maksymalnie 50 dp, aby wartość atrybutu minResizeHeight była mniejsza niż 51 dp, ponieważ w trybie poziomym jedna komórka ma wysokość co najmniej 51 dp.
Rozmiar każdego widżetu można zmieniać w zakresie między atrybutami minResizeWidth/minResizeHeight i maxResizeWidth/maxResizeHeight, co oznacza, że musi on dostosowywać się 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 xmlns:android="http://schemas.android.com/apk/res/android" android:targetCellWidth="3" android:targetCellHeight="2" android:minWidth="180dp" android:minHeight="110dp"> </appwidget-provider>
Oznacza to, że domyślny rozmiar widżetu to 3 x 2 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ż ustawić te atrybuty:
<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>
Zgodnie z powyższymi atrybutami szerokość widżetu można zmieniać w zakresie od 180 dp do 530 dp, a jego wysokość – od 110 dp do 450 dp. Rozmiar widżetu można zmienić z 3 x 2 na 5 x 2 komórki, o ile spełnione są te warunki:
- Urządzenie ma siatkę 5 x 4.
- Mapowanie liczby komórek na dostępny rozmiar w dp jest zgodne z tabelą przedstawiającą szacunkowe wymiary minimalne na tej stronie.
- Widżet dostosowuje się do tego zakresu rozmiarów.
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))
Załóżmy, że widżet używa układów elastycznych zdefiniowanych w poprzednich fragmentach kodu. Oznacza to, że układ określony jako R.layout.widget_weather_forecast_small jest używany od 180 dp (minResizeWidth) x 110 dp (minResizeHeight) do 269 x 279 dp (następne punkty odcięcia – 1). Podobnie R.layout.widget_weather_forecast_medium jest używany w zakresie od 270 x 110 dp do 270 x 279 dp, a R.layout.widget_weather_forecast_large – 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 poniższych przykładach.
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.