Tworzenie prostego widżetu

Widżety to miniaturowe widoki aplikacji, które możesz umieścić w innych aplikacjach, np. na ekranie głównym, i otrzymywać okresowe aktualizacje. Widoki te w interfejsie są nazywane widżetami. Można je publikować, korzystając z dostawcy widżetu aplikacji (lub dostawcy widżetu). Komponent aplikacji, który zawiera inne widżety, jest nazywany hostem widżetów aplikacji (lub hostem widżetów). Rysunek 1 przedstawia przykładowy widżet muzyczny:

Przykład widżetu muzycznego
Rysunek 1. Przykład widżetu muzycznego.

W tym dokumencie opisano sposób publikowania widżetu przy użyciu dostawcy widżetu. Szczegółowe informacje na temat tworzenia własnego AppWidgetHost do hostowania widżetów aplikacji znajdziesz w artykule Tworzenie hosta widżetów.

Więcej informacji o projektowaniu widżetu znajdziesz w artykule Omówienie widżetów aplikacji.

Komponenty widżetów

Aby utworzyć widżet, potrzebujesz tych podstawowych komponentów:

AppWidgetProviderInfo obiekt
Opisuje metadane widżetu, takie jak jego układ, częstotliwość aktualizacji i klasa AppWidgetProvider. Parametr AppWidgetProviderInfo jest zdefiniowany w pliku XML zgodnie z opisem w tym dokumencie.
AppWidgetProvider zajęcia
Definiuje podstawowe metody umożliwiające programistyczny interfejs użytkownika widżeta. Dzięki temu będziesz otrzymywać komunikaty o aktualizacjach, włączeniu, wyłączeniu lub usunięciu widżetu. Zadeklarujesz właściwość AppWidgetProvider w pliku manifestu, a następnie zaimplementujesz ją zgodnie z opisem w tym dokumencie
.
Wyświetl układ
Określa początkowy układ widżetu. Układ jest zdefiniowany w formacie XML zgodnie z opisem w tym dokumencie.

Rysunek 2 pokazuje, jak te komponenty wpisują się w ogólny proces przetwarzania widżetów aplikacji.

Proces przetwarzania widżetu aplikacji
Rysunek 2. Proces przetwarzania widżetu aplikacji.

Jeśli Twój widżet wymaga konfiguracji użytkownika, wdróż aktywność związaną z konfiguracją widżetu aplikacji. Ta aktywność pozwala użytkownikom modyfikować ustawienia widżetu, na przykład strefę czasową widżetu zegara.

Zalecamy też wprowadzenie tych ulepszeń: elastyczne układy widżetów, różne ulepszenia, zaawansowane widżety, widżety kolekcji oraz utworzenie hosta widżetów.

Deklarowanie pliku XML AppWidgetProviderInfo

Obiekt AppWidgetProviderInfo definiuje podstawowe cechy widżetu. Zdefiniuj obiekt AppWidgetProviderInfo w pliku zasobów XML za pomocą pojedynczego elementu <appwidget-provider> i zapisz go w folderze res/xml/ projektu.

Widać to w tym przykładzie:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:targetCellWidth="1"
    android:targetCellHeight="1"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="120dp"
    android:updatePeriodMillis="86400000"
    android:description="@string/example_appwidget_description"
    android:previewLayout="@layout/example_appwidget_preview"
    android:initialLayout="@layout/example_loading_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

Atrybuty rozmiaru widżetów

Domyślny ekran główny umieszcza widżety w oknie na podstawie siatki komórek o określonej wysokości i szerokości. Większość ekranów głównych zezwala widżetom na przyjmowanie tylko tych rozmiarów, które są wielokrotnościami liczb całkowitych komórek siatki, np. 2 komórki w poziomie i 3 komórki w pionie.

Atrybuty rozmiaru widżetu pozwalają określić domyślny rozmiar widżetu oraz określić dolne i górne granice rozmiaru widżetu. W tym kontekście domyślny rozmiar widżetu to jego rozmiar po dodaniu go do ekranu głównego.

W tabeli poniżej opisujemy atrybuty <appwidget-provider> związane z rozmiarem widżetu:

Atrybuty i opis
targetCellWidth i targetCellHeight (Android 12), minWidth i minHeight
  • Począwszy od Androida 12 atrybuty targetCellWidth i targetCellHeight określają domyślny rozmiar widżetu w postaci komórek siatki. Te atrybuty ignorowane w Androidzie 11 i starszych oraz można je zignorować, jeśli ekran główny nie obsługuje układu opartego na siatce.
  • Atrybuty minWidth i minHeight określają domyślny rozmiar widżetu w dp. Jeśli wartości minimalnej szerokości lub wysokości widżetu nie są zgodne z wymiarami komórek, wartości są zaokrąglane w górę do najbliższego rozmiaru komórki.
Zalecamy określenie obu zestawów atrybutów – targetCellWidth i targetCellHeight oraz minWidth i minHeight – dzięki temu aplikacja będzie mogła wrócić do korzystania z minWidth i minHeight, jeśli urządzenie użytkownika nie obsługuje targetCellWidth i targetCellHeight. Jeśli są obsługiwane, atrybuty targetCellWidth i targetCellHeight mają pierwszeństwo przed atrybutami minWidth i minHeight.
minResizeWidth i minResizeHeight Określ absolutny minimalny rozmiar widżetu. Te wartości określają rozmiar, pod którym widżet jest nieczytelny lub z innego powodu bezużyteczny. Użycie tych atrybutów umożliwia użytkownikowi zmianę rozmiaru widżetu do rozmiaru mniejszego niż domyślny. Atrybut minResizeWidth jest ignorowany, jeśli ma wartość większą niż minWidth lub jeśli zmiana rozmiaru w poziomie nie jest włączona. Zobacz resizeMode. Podobnie atrybut minResizeHeight jest ignorowany, jeśli ma wartość większą niż minHeight lub jeśli zmiana rozmiaru w pionie nie jest włączona.
maxResizeWidth i maxResizeHeight Określ zalecany maksymalny rozmiar widżetu. Jeśli wartości nie są wielokrotnością wymiarów komórki siatki, są zaokrąglane w górę do najbliższego rozmiaru komórki. Atrybut maxResizeWidth jest ignorowany, jeśli ma wartość mniejszą niż minWidth lub jeśli nie jest włączona zmiana rozmiaru w poziomie. Zobacz resizeMode. Podobnie atrybut maxResizeHeight jest ignorowany, jeśli ma wartość większą niż minHeight lub jeśli zmiana rozmiaru w pionie nie jest włączona. Wprowadzona w Androidzie 12.
resizeMode Określa reguły, według których można zmieniać rozmiar widżetu. Możesz użyć tego atrybutu, aby zmienić rozmiar widżetów ekranu głównego w poziomie, w pionie lub na obu osiach. Użytkownicy mogą kliknąć i przytrzymać widżet, aby wyświetlić jego uchwyty zmiany rozmiaru, a następnie przeciągnąć poziome lub pionowe uchwyty, aby zmienić jego rozmiar na siatce układu. Wartości atrybutu resizeMode to horizontal, vertical i none. Aby zadeklarować widżet jako widżet z możliwością zmiany rozmiaru w poziomie i w pionie, użyj właściwości horizontal|vertical.

Przykład

Aby pokazać, jak atrybuty z poprzedniej tabeli wpływają na rozmiar widżetu, przyjmijmy te specyfikacje:

  • Komórka siatki ma szerokość 30 dp i wysokość 50 dp.
  • Podano następującą specyfikację atrybutu:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="80dp"
    android:minHeight="80dp"
    android:targetCellWidth="2"
    android:targetCellHeight="2"
    android:minResizeWidth="40dp"
    android:minResizeHeight="40dp"
    android:maxResizeWidth="120dp"
    android:maxResizeHeight="120dp"
    android:resizeMode="horizontal|vertical" />

Od Androida 12:

Użyj atrybutów targetCellWidth i targetCellHeight jako domyślnego rozmiaru widżetu.

Domyślny rozmiar widżetu to 2 x 2. Rozmiar widżetu można zmniejszyć do 2 x 1 lub do 4 x 3.

Android 11 lub starszy:

Aby obliczyć domyślny rozmiar widżetu, użyj atrybutów minWidth i minHeight.

Domyślna szerokość = Math.ceil(80 / 30) = 3

Domyślna wysokość = Math.ceil(80 / 50) = 2

Domyślny rozmiar widżetu to 3 x 2. Rozmiar widżetu można zmniejszyć do 2 x 1 lub do pełnego ekranu.

Dodatkowe atrybuty widżetu

W tabeli poniżej opisujemy atrybuty <appwidget-provider> odnoszące się do jakości innych niż rozmiar widżetu.

Atrybuty i opis
updatePeriodMillis Określa, jak często platforma widżetu żąda aktualizacji z AppWidgetProvider, wywołując metodę wywołania zwrotnego onUpdate(). Przy użyciu tej wartości nie możemy zagwarantować, że aktualizacja nastąpi dokładnie na czas. W celu oszczędzania baterii zalecamy rzadkie aktualizowanie, czyli nie częściej niż raz na godzinę. Pełną listę uwag na temat wyboru odpowiedniego okresu aktualizacji znajdziesz w artykule Optymalizacje dotyczące aktualizowania zawartości widżetów.
initialLayout Wskazuje zasób układu, który określa układ widżetu.
configure Definiuje działanie, które ma być uruchamiane, gdy użytkownik doda widżet, i może konfigurować jego właściwości. Więcej informacji znajdziesz w artykule Zezwalanie użytkownikom na konfigurowanie widżetów. Od Androida 12 aplikacja może pomijać wstępną konfigurację. Więcej informacji znajdziesz w sekcji Używanie domyślnej konfiguracji widżetu.
description Określa opis selektora widżetów, które będzie wyświetlany w przypadku widżetu. Wprowadzona w Androidzie 12.
previewLayout (Android 12) i previewImage (Android 11 i starsze)
  • Począwszy od Androida 12 atrybut previewLayout określa skalowalny podgląd, który podajesz jako układ XML z domyślnym rozmiarem widżetu. Najlepiej, gdy kod XML układu określony jako ten atrybut to ten sam kod XML układu, co rzeczywisty widżet z realistycznymi wartościami domyślnymi.
  • W Androidzie 11 i starszych atrybut previewImage określa podgląd wyglądu widżetu po jego skonfigurowaniu, który użytkownik widzi po wybraniu widżetu. Jeśli nie zostanie podana, użytkownik zobaczy ikonę programu uruchamiającego aplikację. To pole odpowiada atrybutowi android:previewImage w elemencie <receiver> w pliku AndroidManifest.xml.
Uwaga: zalecamy określenie zarówno atrybutów previewImage, jak i previewLayout, aby aplikacja mogła wrócić do korzystania z previewImage, jeśli urządzenie użytkownika nie obsługuje previewLayout. Więcej informacji znajdziesz w artykule o zgodności wstecznej ze skalowalnymi podglądami widżetów.
autoAdvanceViewId Określa identyfikator widoku podrzędnego widżetu, który jest automatycznie przesuwany przez host widżetu.
widgetCategory Określa, czy widżet może być wyświetlany na ekranie głównym (home_screen), na ekranie blokady (keyguard) lub w obu tych miejscach. W przypadku Androida 5.0 lub nowszego prawidłowa jest tylko home_screen.
widgetFeatures Deklaruje funkcje obsługiwane przez widżet. Jeśli na przykład chcesz, aby widżet używał swojej domyślnej konfiguracji, gdy użytkownik go doda, podaj zarówno flagi configuration_optional, jak i reconfigurable. Pomija to uruchamianie działania konfiguracji po dodaniu widżetu przez użytkownika. Użytkownik może nadal ponownie skonfigurować widżet.

Używanie klasy AppWidgetProvider do obsługi komunikatów widżetu

Klasa AppWidgetProvider obsługuje transmisje widżetów i ich aktualizowanie w odpowiedzi na zdarzenia cyklu życia widżetu. W sekcjach poniżej dowiesz się, jak zadeklarować właściwość AppWidgetProvider w pliku manifestu, a następnie ją wdrożyć.

Zadeklarowanie widżetu w pliku manifestu

Najpierw zadeklaruj klasę AppWidgetProvider w pliku AndroidManifest.xml aplikacji, jak pokazano w tym przykładzie:

<receiver android:name="ExampleAppWidgetProvider"
                 android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
</receiver>

Element <receiver> wymaga atrybutu android:name, który określa obiekt AppWidgetProvider używany przez widżet. Komponentu nie można eksportować, chyba że do AppWidgetProvider musi przesłać go osobny proces, co zwykle nie jest konieczne.

Element <intent-filter> musi zawierać element <action> z atrybutem android:name. Ten atrybut określa, że AppWidgetProvider akceptuje transmisję ACTION_APPWIDGET_UPDATE. To jedyna transmisja, którą musisz wyraźnie zadeklarować. W razie potrzeby AppWidgetManager automatycznie wysyła wszystkie pozostałe komunikaty widżetu do elementu AppWidgetProvider.

Element <meta-data> określa zasób AppWidgetProviderInfo i wymaga tych atrybutów:

  • android:name: określa nazwę metadanych. Użyj android.appwidget.provider, aby określić dane jako deskryptor AppWidgetProviderInfo.
  • android:resource: określa lokalizację zasobu AppWidgetProviderInfo.

Implementowanie klasy AppWidgetProvider

Klasa AppWidgetProvider stanowi rozwinięcie klasy BroadcastReceiver jako klasy ułatwiającej obsługę transmisji widżetu. Otrzymuje tylko te transmisje zdarzeń, które są istotne dla widżetu, na przykład informacje o tym, kiedy widżet jest aktualizowany, usuwany, włączony lub wyłączony. Kiedy występują takie zdarzenia transmisji, wywoływane są te metody AppWidgetProvider:

onUpdate()
Jest ono wywoływane do aktualizowania widżetu w interwałach zdefiniowanych przez atrybut updatePeriodMillis w pliku AppWidgetProviderInfo. Więcej informacji znajdziesz w tabeli z opisem dodatkowych atrybutów widżetów na tej stronie.
Ta metoda jest też wywoływana, gdy użytkownik doda widżet, więc wykonuje niezbędną konfigurację, np. definiowanie modułów obsługi zdarzeń dla obiektów View lub uruchamianie zadań wczytywania danych do wyświetlenia w widżecie. Jeśli jednak zadeklarujesz aktywność związaną z konfiguracją bez flagi configuration_optional, ta metoda nie będzie wywoływana podczas dodawania widżetu, ale jest wywoływana przy kolejnych aktualizacjach. Obowiązkiem działania związanego z konfiguracją jest przeprowadzenie pierwszej aktualizacji po zakończeniu konfiguracji. Więcej informacji znajdziesz w artykule Zezwalanie użytkownikom na konfigurowanie widżetów aplikacji.
Najważniejsze wywołanie zwrotne to: onUpdate(). Więcej informacji znajdziesz w sekcji Obsługa zdarzeń za pomocą klasy onUpdate() na tej stronie.
onAppWidgetOptionsChanged()

Ta opcja jest wywoływana przy umieszczaniu widżetu po raz pierwszy i każdej zmianie jego rozmiaru. To wywołanie zwrotne służy do wyświetlania lub ukrywania treści zależnie od zakresów rozmiarów widżetu. Pobierz zakresy rozmiarów (począwszy od Androida 12, listę możliwych rozmiarów, jakie może przyjmować instancja widżetu), wywołując metodę getAppWidgetOptions(), która zwraca element Bundle zawierający:

onDeleted(Context, int[])

Ta funkcja jest wywoływana za każdym razem, gdy widżet zostanie usunięty z hosta widżetów.

onEnabled(Context)

Jest ono wywoływane podczas tworzenia instancji widżetu po raz pierwszy. Jeśli na przykład użytkownik doda 2 instancje Twojego widżetu, nazwa ta zostanie wywołana tylko za pierwszym razem. Jeśli musisz otworzyć nową bazę danych lub przeprowadzić inną konfigurację, którą trzeba wykonać tylko raz dla wszystkich instancji widżetów, jest to dobre miejsce.

onDisabled(Context)

Jest ono wywoływane, gdy ostatnie wystąpienie widżetu zostanie usunięte z hosta widżetu. W tym miejscu usuwasz wszystkie swoje zadania w onEnabled(Context), na przykład usuwasz tymczasową bazę danych.

onReceive(Context, Intent)

Jest ono wywoływane dla każdej transmisji i przed każdą z poprzednich metod wywołania zwrotnego. Zwykle nie musisz implementować tej metody, ponieważ domyślna implementacja AppWidgetProvider filtruje wszystkie komunikaty widżetu i w razie potrzeby wywołuje poprzednie metody.

Musisz zadeklarować implementację klasy AppWidgetProvider jako odbiornik, używając elementu <receiver> w obiekcie AndroidManifest. Więcej informacji znajdziesz w sekcji Deklarowanie widżetu w pliku manifestu na tej stronie.

Obsługa zdarzeń za pomocą klasy onUpdate()

Najważniejszym wywołaniem zwrotnym AppWidgetProvider jest onUpdate(), ponieważ jest ono wywoływane po dodaniu każdego widżetu do hosta, chyba że używasz działania konfiguracyjnego bez flagi configuration_optional. Jeśli Twój widżet akceptuje dowolne zdarzenia interakcji użytkownika, zarejestruj moduły obsługi zdarzeń w tym wywołaniu zwrotnym. Jeśli Twój widżet nie tworzy plików tymczasowych ani baz danych ani nie wykonuje innych czynności wymagających czyszczenia, onUpdate() może być jedyną metodą wywołania zwrotnego, którą musisz zdefiniować.

Jeśli na przykład chcesz widżet z przyciskiem uruchamiającym działanie po kliknięciu, możesz użyć tej implementacji AppWidgetProvider:

Kotlin

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Java

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

Ten element AppWidgetProvider definiuje tylko metodę onUpdate() przy użyciu jej do tworzenia PendingIntent, który uruchamia element Activity i dołącza go do przycisku widżetu za pomocą setOnClickPendingIntent(int, PendingIntent). Zawiera pętlę, która powtarza się po każdym wpisie w appWidgetIds. Jest to tablica identyfikatorów identyfikujących każdy widżet utworzony przez tego dostawcę. Jeśli użytkownik utworzy więcej niż jedną instancję widżetu, będą one aktualizowane jednocześnie. Dla wszystkich instancji widżetu jest jednak zarządzany tylko 1 harmonogram updatePeriodMillis. Jeśli na przykład harmonogram aktualizacji jest ustawiony na co 2 godziny, a drugie wystąpienie widżetu zostanie dodane po godzinie od pierwszego, oba zostaną zaktualizowane w okresie zdefiniowanym przez pierwszy, a drugi okres aktualizacji zostanie zignorowany. Obie są aktualizowane co 2 godziny, a nie co godzinę.

Więcej informacji znajdziesz w przykładowej klasie ExampleAppWidgetProvider.java.

Odbieranie intencji transmisji widżetu

AppWidgetProvider to klasa praktyczna. Jeśli chcesz bezpośrednio otrzymywać komunikaty z widżetu, możesz wdrożyć własne źródło BroadcastReceiver lub zastąpić wywołanie zwrotne onReceive(Context,Intent). Intencje, na których Ci zależy, to:

Tworzenie układu widżetu

Musisz zdefiniować początkowy układ widżetu w formacie XML i zapisać go w katalogu res/layout/ projektu. Szczegóły znajdziesz we wskazówkach dotyczących projektowania.

Tworzenie układu widżetu jest proste, jeśli znasz się na układach. Pamiętaj jednak, że układy widżetów bazują na usłudze RemoteViews, która nie obsługuje wszystkich rodzajów układów i widżetów widoku. Nie możesz używać niestandardowych widoków ani podklas widoków obsługiwanych przez RemoteViews.

RemoteViews obsługuje też ViewStub – niewidoczny obiekt View o zerowym rozmiarze, którego można używać do leniwego powiększania zasobów układu w czasie działania.

Obsługa zachowań stanowych

Android 12 dodaje obsługę zachowania stanowego przy użyciu tych istniejących komponentów:

Widżet nadal jest bezstanowy. Aplikacja musi przechowywać stan i rejestrować zdarzenia zmiany stanu.

Przykład widżetu listy zakupów przedstawiającego zachowanie stanowe
Rysunek 3. Przykład działania stanowego.

Poniższy przykładowy kod pokazuje, jak wdrożyć te komponenty.

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

Udostępnij 2 układy: jeden na urządzenia z Androidem 12 lub nowszym w res/layout-v31, a drugi na Androida 11 lub starszego w domyślnym folderze res/layout.

Stosowanie zaokrąglonych rogów

Android 12 wprowadza te parametry systemowe, aby ustawić promień zaokrąglonych rogów widżetu:

Poniższy przykład przedstawia widżet, w którym użyto system_app_widget_background_radius jako narożnika widżetu oraz system_app_widget_inner_radius do wyświetlania jego widoków.

Widżet pokazujący promień tła widżetu i widoki wewnątrz widżetu
Rysunek 4. Zaokrąglone narożniki.

1 Króg widżetu.

2 Króg widoku w widżecie.

Ważne informacje na temat zaokrąglonych rogów

  • Zewnętrzne Menu z aplikacjami i producenci urządzeń mogą zastąpić parametr system_app_widget_background_radius tak, by jego wartość była mniejsza niż 28 dp. Parametr system_app_widget_inner_radius jest zawsze o 8 dp mniejszy niż wartość parametru system_app_widget_background_radius.
  • Jeśli Twój widżet nie używa @android:id/background ani nie zdefiniujesz tła, które przycina jego zawartość na podstawie obrysu (przy ustawieniu android:clipToOutline ma wartość true), program uruchamiający automatycznie identyfikuje tło i przycina widżet za pomocą prostokąta z zaokrąglonymi narożnikami o maksymalnych 16 dp. Zobacz Sprawdzanie, czy widżet jest zgodny z Androidem 12.

Aby zapewnić zgodność widżetów z poprzednimi wersjami Androida, zalecamy zdefiniowanie atrybutów niestandardowych i zastosowanie motywu niestandardowego do zastąpienia ich w Androidzie 12, jak pokazano w tych przykładowych plikach XML:

/values/attrs.xml

<resources>
  <attr name="backgroundRadius" format="dimension" />
</resources>

/values/styles.xml

<resources>
  <style name="MyWidgetTheme">
    <item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
  </style>
</resources>

/values-31/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
    <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
  </style>
</resources>

/drawable/my_widget_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="?attr/backgroundRadius" />
  ...
</shape>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />