Vorschauen zur Widget-Auswahl hinzufügen

Wenn Sie die Widget-Auswahl in Ihrer App verbessern möchten, stellen Sie auf Geräten mit Android 15 und höher eine generierte Widget-Vorschau, auf Geräten mit Android 12 bis Android 14 eine skalierte Widget-Vorschau (durch Angabe eines previewLayout) und auf Geräten mit früheren Versionen ein previewImage bereit.

Mit generierten Widget-Vorschauen können Sie dynamische, personalisierte Vorschauen für Ihre Widgets erstellen, die genau zeigen, wie sie auf dem Startbildschirm eines Nutzers aussehen werden. Ab Android 15 werden sie über eine Push-API bereitgestellt. Das bedeutet, dass Ihre App die Vorschau zu einem beliebigen Zeitpunkt während ihres Lebenszyklus bereitstellt, ohne eine explizite Anfrage vom Widget-Host zu erhalten.

Weitere Informationen findest du im YouTube-Video Enrich your app with live updates and widgets (Apps mit Livemeldungen und Widgets anreichern).

Generierte Vorschauen hinzufügen

Wenn Sie auf einem Gerät mit Android 15 oder höher generierte Widget-Vorschauen anzeigen möchten, müssen Sie zuerst den Wert compileSdk in der Datei build.gradle des Moduls auf 35 oder höher setzen, damit Sie der Widget-Auswahl RemoteViews zur Verfügung stellen können.

Apps können setWidgetPreview in AppWidgetManager verwenden. Um Missbrauch zu verhindern und die Systemintegrität zu gewährleisten, ist die setWidgetPreview eine API mit Ratenbegrenzung. Das Standardlimit beträgt etwa zwei Aufrufe pro Stunde.

Es gibt keinen Callback vom System, um Vorschauen bereitzustellen. Ihre App muss also entscheiden, wann setWidgetPreviews aufgerufen werden soll. Die Aktualisierungsstrategie hängt vom Anwendungsfall des Widgets ab:

  • Wenn das Widget statische Informationen enthält oder eine Schnellaktion ist, legen Sie die Vorschau fest, wenn die App zum ersten Mal gestartet wird.
  • Sie können die Vorschau festlegen, sobald Ihre App Daten enthält, z. B. nach der Anmeldung eines Nutzers oder der Ersteinrichtung.
  • Sie können eine regelmäßige Aufgabe einrichten, um die Vorabversionen in einem bestimmten Intervall zu aktualisieren.

Im folgenden Beispiel wird eine XML-Widget-Layoutressource geladen und als Vorschau festgelegt. Damit setWidgetPreview in diesem Snippet als Methode angezeigt wird, ist eine compileSdk-Build-Einstellung von 35 oder höher erforderlich.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    RemoteViews("com.example", R.layout.widget_preview)
)

Skalierbare Widget-Vorschauen hinzufügen

Ab Android 12 ist die Widget-Vorschau in der Widget-Auswahl skalierbar. Sie stellen es als XML-Layout bereit, das auf die Standardgröße des Widgets festgelegt ist. Bisher war die Widget-Vorschau eine statische zeichenfähige Ressource, was in einigen Fällen dazu führte, dass die Vorschau nicht genau wiedergab, wie Widgets auf dem Startbildschirm angezeigt werden.

Wenn Sie skalierbare Widget-Vorschauen implementieren möchten, verwenden Sie stattdessen das Attribut previewLayout des Elements appwidget-provider, um ein XML-Layout bereitzustellen:

<appwidget-provider
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>

Wir empfehlen, dasselbe Layout wie für das eigentliche Widget zu verwenden, mit realistischen Standard- oder Testwerten. Die meisten Apps verwenden dieselbe previewLayout und initialLayout. Eine Anleitung zum Erstellen genauer Vorschaulayouts finden Sie unter Genaue Vorschauen mit dynamischen Elementen erstellen.

Wir empfehlen, sowohl das Attribut previewLayout als auch das Attribut previewImage anzugeben, damit deine App auf previewImage zurückgreifen kann, wenn das Gerät des Nutzers previewLayout nicht unterstützt. Das Attribut previewLayout hat Vorrang vor dem Attribut previewImage.

Statische Widget-Vorschauen für Abwärtskompatibilität hinzufügen

Wenn Sie möchten, dass Widget-Auswahltools unter Android 11 (API-Level 30) oder niedriger Vorschauen Ihres Widgets anzeigen, oder als Fallback für skalierbare Vorschauen, geben Sie das Attribut previewImage an.

Wenn Sie das Erscheinungsbild des Widgets ändern, aktualisieren Sie das Vorschaubild.

Dieses Attribut wird auch als Fallback für generierte Vorschauen verwendet, wenn du keine mit setWidgetPreview festgelegt hast.

Genaue Vorschauen mit dynamischen Elementen erstellen

Abbildung 1: Widget-Vorschau ohne Listenelemente

In diesem Abschnitt wird die empfohlene Vorgehensweise zum Anzeigen mehrerer Elemente in einer Widget-Vorschau für ein Widget mit einer Sammlungsansicht erläutert, d. h. für ein Widget, das eine ListView, GridView oder StackView verwendet. Dies gilt für skalierbare Widget-Vorschauen, nicht für generierte Vorschauen.

Wenn dein Widget eine dieser Ansichten verwendet, kann das Erstellen einer skalierbaren Vorschau durch Bereitstellen des tatsächlichen Widget-Layouts direkt in previewLayout die Nutzerfreundlichkeit beeinträchtigen, wenn in der Widget-Vorschau keine Elemente angezeigt werden. Das liegt daran, dass die Daten der Sammlungsansicht zur Laufzeit dynamisch festgelegt werden. Das sieht dann ähnlich aus wie in Abbildung 1.

Damit Vorschauen von Widgets mit Sammlungsansichten in der Widget-Auswahl richtig angezeigt werden, empfehlen wir, eine separate Layoutdatei nur für die Vorschau zu verwenden. Diese separate Layoutdatei sollte Folgendes enthalten:

  • Das tatsächliche Widget-Layout.
  • Eine Platzhalter-Sammlungsansicht mit fiktiven Elementen. Sie können beispielsweise einen ListView simulieren, indem Sie einen Platzhalter-LinearLayout mit mehreren gefälschten Listenelementen bereitstellen.

Hier ist ein Beispiel für ein ListView mit einer separaten Layoutdatei:

// res/layout/widget_preview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/widget_background"
   android:orientation="vertical">

    // Include the actual widget layout that contains ListView.
    <include
        layout="@layout/widget_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    // The number of fake items you include depends on the values you provide
    // for minHeight or targetCellHeight in the AppWidgetProviderInfo
    // definition.

    <TextView android:text="@string/fake_item1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

    <TextView android:text="@string/fake_item2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

</LinearLayout>

Geben Sie die Layoutdatei für die Vorschau an, wenn Sie das Attribut previewLayout der Metadaten AppWidgetProviderInfo angeben. Sie geben weiterhin das tatsächliche Widget-Layout für das Attribut initialLayout an und verwenden das tatsächliche Widget-Layout, wenn Sie zur Laufzeit ein RemoteViews erstellen.

<appwidget-provider
    previewLayout="@layout/widget_preview"
    initialLayout="@layout/widget_view" />

Komplexe Listenelemente

Das Beispiel im vorherigen Abschnitt enthält gefälschte Listenelemente, da die Listenelemente TextView-Objekte sind. Es kann komplexer sein, gefälschte Elemente bereitzustellen, wenn die Elemente komplexe Layouts sind.

Betrachten Sie ein Listenelement, das in widget_list_item.xml definiert ist und aus zwei TextView-Objekten besteht:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView android:id="@id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_title" />

    <TextView android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_content" />
</LinearLayout>

Wenn Sie gefälschte Listenelemente bereitstellen möchten, können Sie das Layout mehrmals einfügen. Dadurch sind jedoch alle Listenelemente identisch. So stellen Sie eindeutige Listenelemente bereit:

  1. Erstellen Sie eine Reihe von Attributen für die Textwerte:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. Verwenden Sie diese Attribute, um den Text festzulegen:

    <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        <TextView android:id="@id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetTitle" />
    
        <TextView android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetContent" />
    </LinearLayout>
    
  3. Erstellen Sie so viele Stile, wie für die Vorschau erforderlich sind. Definieren Sie die Werte in jedem Stil neu:

    <resources>
    
        <style name="Theme.Widget.ListItem">
            <item name="widgetTitle"></item>
            <item name="widgetContent"></item>
        </style>
        <style name="Theme.Widget.ListItem.Preview1">
            <item name="widgetTitle">Fake Title 1</item>
            <item name="widgetContent">Fake content 1</item>
        </style>
        <style name="Theme.Widget.ListItem.Preview2">
            <item name="widgetTitle">Fake title 2</item>
            <item name="widgetContent">Fake content 2</item>
        </style>
    
    </resources>
    
  4. Wenden Sie die Stile auf die fiktiven Elemente im Vorschaulayout an:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" ...>
    
        <include layout="@layout/widget_view" ... />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview1" />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview2" />
    
    </LinearLayout>