Na tej stronie opisujemy ulepszenia dotyczące rozmiaru widżetów i większą elastyczność wprowadzonych w Androidzie 12 (poziom API 31). Znajdziesz w nim też informacje o określaniu rozmiaru widżetu.
Używanie ulepszonych interfejsów API do obsługi rozmiarów i układów widżetów
Począwszy od Androida 12 (poziom interfejsu API 31) możesz udostępniać bardziej szczegółowe atrybuty rozmiaru i elastyczne układy, wykonując te czynności zgodnie z opisem w sekcjach poniżej:
Udostępnianie układów elastycznych lub ścisłych układów.
W poprzednich wersjach Androida można było pobrać zakresy rozmiarów widżetu za pomocą rozszerzeń 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 zawsze działa. W przypadku widżetów kierowanych na Androida 12 lub nowszego zalecamy zastosowanie elastycznego lub precyzyjnego układu.
Określ dodatkowe ograniczenia rozmiaru widżetów
Android 12 dodaje interfejsy API, które zapewniają bardziej niezawodny rozmiar widżetu na różnych urządzeniach o różnych rozmiarach ekranu.
Oprócz istniejących atrybutów minWidth
,
minHeight
,
minResizeWidth
i minResizeHeight
użyj tych nowych atrybutów appwidget-provider
:
targetCellWidth
itargetCellHeight
: określają docelowy rozmiar widżetu w postaci komórek siatki programu uruchamiającego. Jeśli atrybut jest zdefiniowany, używane są te atrybuty zamiastminWidth
lubminHeight
.maxResizeWidth
imaxResizeHeight
: określają maksymalny rozmiar widżetu, który program uruchamiający pozwala użytkownikowi na zmianę rozmiaru.
Poniższy kod XML pokazuje, jak korzystać z atrybutów dobierania rozmiaru.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
Zastosowanie układów elastycznych
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 przeznaczony dla różnych rozmiarów. Jeśli to niemożliwe, możesz podać 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 poprawia stan systemu, ponieważ system nie musi wybudzać aplikacji za każdym razem, gdy wyświetla widżet w innym rozmiarze.
Poniższy przykładowy kod pokazuje, jak udostępnić 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>
Fragment kodu oznacza, że:
smallView
obsługuje parametry od 160 dp (minResizeWidth
) × 110 dp (minResizeHeight
) do 160 dp × 199 dp (następny punkt odcięcia – 1 dp).tallView
obsługuje wymiary od 160 dp × 200 do 214 dp (następny punkt odcięcia – 1) × 200 dp.wideView
obsługuje wymiary od 215 dp × 110 dp (minResizeHeight
) do 250 dp (maxResizeWidth
) × 200 dp (maxResizeHeight
).
Widżet musi obsługiwać rozmiary od minResizeWidth
× minResizeHeight
do maxResizeWidth
× maxResizeHeight
. W tym zakresie możesz określić, od którego punktu granicznego przełączać układy.
![Przykład układu elastycznego](https://developer.android.google.cn/static/images/appwidgets/size-range.gif?authuser=1&hl=pl)
Wybierz dokładny układ
Jeśli nie możesz zastosować małego zestawu układów elastycznych, możesz zamiast tego przygotować różne układy dostosowane do rozmiarów, w których wyświetla się widżet. Zwykle jest to 2 rozmiary dla telefonów (tryb pionowy i poziomy) i 4 rozmiary dla urządzeń składanych.
Aby wdrożyć to rozwiązanie, aplikacja musi wykonać te czynności:
Przeładuj element
AppWidgetProvider.onAppWidgetOptionsChanged()
, który jest wywoływany po zmianie zestawu rozmiarów.Wywołaj
AppWidgetManager.getAppWidgetOptions()
, który zwracaBundle
z rozmiarami.Uzyskaj dostęp do klucza
AppWidgetManager.OPTION_APPWIDGET_SIZES
z systemuBundle
.
Ten przykładowy kod pokazuje, jak określić 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ć atrybuty targetCellWidth
i targetCellHeight
dla urządzeń z Androidem 12 lub nowszym albo minWidth
i minHeight
w przypadku wszystkich wersji Androida. Musi to być minimalna ilość miejsca wykorzystywanego domyślnie. Gdy jednak użytkownicy dodają widżet do ekranu głównego, zajmuje on zwykle więcej miejsca niż określona przez Ciebie minimalna szerokość i wysokość.
Ekrany główne Androida to siatka dostępnych miejsc, w których można umieszczać widżety i ikony. Siatka może się różnić w zależności od urządzenia. Na przykład wiele telefonów oferuje siatkę 5 x 4, a na tabletach może być większa. Po dodaniu widżet jest rozciągnięty, aby zajmował w poziomie i pionie minimalną liczbę komórek wymaganych do spełnienia ograniczeń dotyczących targetCellWidth
i targetCellHeight
na urządzeniach z Androidem 12 lub nowszym albo ograniczeń minWidth
i minHeight
na urządzeniach z Androidem 11 (poziom interfejsu API 30) lub niższym.
Szerokość 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. Tabela poniżej pozwala w przybliżeniu oszacować minimalne wymiary widżetu w typowych telefonach z siatką 5 x 4 przy uwzględnieniu żądanej liczby zajętych komórek:
Liczba komórek (szerokość x wysokość) | Dostępny rozmiar w trybie pionowym (dp) | Dostępny rozmiar w trybie poziomym (dp) |
---|---|---|
1 × 1 | 57x102dp | 127x51dp |
2 × 1 | 130x102dp | 269x51dp |
3 × 1 | 203x102dp | 412x51dp |
10 × 15 cm | 276x102dp | 554x51dp |
13 × 18 cm | 349x102dp | 697x51dp |
13 × 28 cm | 349x220dp | 697x117dp |
13 × 15 cm | 349x337dp | 697x184dp |
13 × 15 cm | 349x455dp | 697x250dp |
… | ... | … |
N × M | (73 n – 16) x (118 m – 16) | (142 n – 15) x (66 m–15) |
Użyj rozmiarów komórek w trybie pionowym, aby podać wartości atrybutów minWidth
, minResizeWidth
i maxResizeWidth
. W podobny sposób używaj rozmiarów komórek w trybie poziomym, aby podawać wartości w atrybutach minHeight
, minResizeHeight
i maxResizeHeight
.
Wynika to z tego, że szerokość komórki jest zwykle mniejsza w trybie pionowym niż w trybie poziomym, a wysokość komórki jest zwykle mniejsza w trybie poziomym niż w trybie pionowym.
Jeśli na przykład na telefonie Google Pixel 4 chcesz zmniejszyć szerokość widżetu do jednej komórki, ustaw dla minResizeWidth
wartość nie większą niż 56 dp, tak by wartość atrybutu minResizeWidth
była mniejsza niż 57 dp, bo komórka ma co najmniej 57 dp w orientacji pionowej.
I podobnie, jeśli chcesz, by wysokość widżetu można było zmieniać w jednej komórce na tym samym urządzeniu, musisz ustawić minResizeHeight
na maksymalnie 50 dp, aby wartość atrybutu minResizeHeight
była mniejsza niż 51 dp, bo 1 komórka ma wysokość co najmniej 51 dp w trybie poziomym.
Rozmiar każdego widżetu można zmienić w zakresie rozmiarów z atrybutów minResizeWidth
/minResizeHeight
i maxResizeWidth
/maxResizeHeight
, co oznacza, że musi dostosować się do dowolnego rozmiaru pomiędzy nimi.
Aby na przykład ustawić domyślny rozmiar widżetu w miejscu docelowym, możesz ustawić 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 3 x 2 komórki (zgodnie z atrybutami targetCellWidth
i targetCellHeight
) lub 180 × 110 dp (zgodnie z zasadami minWidth
i minHeight
) w przypadku urządzeń z Androidem 11 lub starszym. W tym drugim przypadku rozmiar
komórek może się różnić w zależności od urządzenia.
Aby ustawić obsługiwane zakresy rozmiarów widżetu, możesz ustawić te atrybuty:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
Zgodnie z poprzednimi atrybutami szerokość widżetu można zmieniać od 180 do 530 dp, a jego wysokość można zmieniać z 110 do 450 dp. Rozmiar widżetu można zmieniać z komórek 3 x 2 na 5 x 2, o ile są spełnione te warunki:
- Urządzenie ma siatkę 5 x 4.
- Mapowanie liczby komórek na dostępny rozmiar w dps jest zgodne z tabelą szacowaną minimalną liczbą wymiarów na tej stronie.
- Widżet dostosowuje 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 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ępny próg – 1). Podobnie R.layout.widget_weather_forecast_medium
jest używany od 270 x 110 dp do 270 x 279 dp, a R.layout.widget_weather_forecast_large
jest stosowany od 270 x 280 do 530 dp (maxResizeWidth
) x 450 dp (maxResizeHeight
).
Gdy użytkownik zmienia rozmiar widżetu, jego wygląd dostosowuje się do rozmiaru komórek, jak widać w przykładach poniżej.
![Przykładowy widżet pogody w najmniejszym rozmiarze siatki 3 x 2. Interfejs z nazwą lokalizacji (Tokio), temperaturą (14°) i symbolem wskazującym częściowe zachmurzenie.](https://developer.android.google.cn/static/images/appwidgets/weather-size-3x2.png?authuser=1&hl=pl)
R.layout.widget_weather_forecast_small
.![Przykładowy widżet pogody o średnim rozmiarze 4 x 2. Zmiana rozmiaru widżetu w ten sposób opiera się na całym UI z poprzedniego rozmiaru widżetu i dodaje etykietę „W większości chmury” oraz prognozę temperatur między 16:00 a 19:00.](https://developer.android.google.cn/static/images/appwidgets/weather-size-4x2.png?authuser=1&hl=pl)
R.layout.widget_weather_forecast_medium
.![Przykładowy widżet pogody w średnim rozmiarze 5 x 2. Zmiana rozmiaru widżetu w ten sposób powoduje taki sam interfejs jak w poprzednim rozmiarze, ale jest rozciągnięty o 1 komórkę, aby zajmował więcej miejsca w poziomie.](https://developer.android.google.cn/static/images/appwidgets/weather-size-5x2.png?authuser=1&hl=pl)
R.layout.widget_weather_forecast_medium
.![Przykładowy widżet pogody w dużym rozmiarze 5 x 3. Zmiana rozmiaru widżetu w ten sposób bazuje na wszystkich dotychczasowych rozmiarach widżetów w interfejsie i dodaje do widżetu widok z prognozą pogody na wtorek i środę. Symbole wskazujące słoneczną lub deszczową pogodę oraz wysokie i niskie temperatury w poszczególnych dniach.](https://developer.android.google.cn/static/images/appwidgets/weather-size-5x3.png?authuser=1&hl=pl)
R.layout.widget_weather_forecast_large
.![Przykładowy widżet pogody w dużym rozmiarze 5 x 4. Zmiana rozmiaru widżetu w ten sposób bazuje na wszystkich dotychczasowych rozmiarach widżetu i dodaje czwartek i piątek (oraz odpowiadające im symbole wskazujące rodzaj pogody oraz wysoką i niską temperaturę w poszczególnych dniach).](https://developer.android.google.cn/static/images/appwidgets/weather-size-5x4.png?authuser=1&hl=pl)
R.layout.widget_weather_forecast_large
.