Flexible Widget-Layouts bereitstellen

Auf dieser Seite werden die Optimierungen für die Größe von Widgets und die größere Flexibilität beschrieben, die in Android 12 (API-Level 31) eingeführt wurden. Außerdem erfahren Sie dort, wie Sie die Größe Ihres Widgets festlegen.

Verbesserte APIs für Widgetgrößen und ‑layouts verwenden

Ab Android 12 (API-Ebene 31) können Sie detailliertere Größenattribute und flexible Layouts angeben. Gehen Sie dazu wie in den folgenden Abschnitten beschrieben vor:

  1. Legen Sie zusätzliche Einschränkungen für die Größe von Widgets fest.

  2. Responsive Layouts oder genaue Layouts bereitstellen

In früheren Android-Versionen können Sie die Größe eines Widgets mit den Extras OPTION_APPWIDGET_MIN_WIDTH, OPTION_APPWIDGET_MIN_HEIGHT, OPTION_APPWIDGET_MAX_WIDTH und OPTION_APPWIDGET_MAX_HEIGHT abrufen und dann die Größe des Widgets schätzen. Diese Logik funktioniert jedoch nicht in allen Situationen. Für Widgets, die auf Android 12 oder höher ausgerichtet sind, empfehlen wir responsive oder genaue Layouts.

Zusätzliche Einschränkungen für die Größe von Widgets angeben

Mit Android 12 werden APIs hinzugefügt, mit denen Sie die Größe Ihres Widgets auf verschiedenen Geräten mit unterschiedlichen Bildschirmgrößen zuverlässiger festlegen können.

Verwenden Sie zusätzlich zu den vorhandenen Attributen minWidth, minHeight, minResizeWidth und minResizeHeight die folgenden neuen appwidget-provider-Attribute:

  • targetCellWidth und targetCellHeight: Definieren Sie die Zielgröße des Widgets in Bezug auf die Zellen im Launcher-Raster. Wenn diese Attribute definiert sind, werden sie anstelle von minWidth oder minHeight verwendet.

  • maxResizeWidth und maxResizeHeight: Mit diesen Werten wird die maximale Größe festgelegt, auf die der Nutzer das Widget im Launcher ändern kann.

Im folgenden XML-Code wird gezeigt, wie die Größenattribute verwendet werden.

<appwidget-provider
  ...
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

Responsive Layouts bereitstellen

Wenn sich das Layout je nach Größe des Widgets ändern muss, empfehlen wir, mehrere Layouts zu erstellen, die jeweils für eine Reihe von Größen gelten. Wenn das nicht möglich ist, können Sie auch Layouts basierend auf der genauen Widget-Größe zur Laufzeit bereitstellen, wie auf dieser Seite beschrieben.

Diese Funktion ermöglicht eine reibungslosere Skalierung und insgesamt einen besseren Systemzustand, da das System die Anwendung nicht jedes Mal aktivieren muss, wenn das Widget in einer anderen Größe angezeigt wird.

Im folgenden Codebeispiel wird gezeigt, wie eine Liste von Layouts angegeben wird.

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);
}

Angenommen, das Widget hat die folgenden Attribute:

<appwidget-provider
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

Das bedeutet Folgendes:

  • smallView unterstützt 160 dp (minResizeWidth) × 110 dp (minResizeHeight) bis 160 dp × 199 dp (nächste Grenze, 1 dp).
  • tallView unterstützt 160 × 200 dp bis 214 dp (nächster Grenzwert – 1) × 200 dp.
  • wideView unterstützt 215 × 110 dp (minResizeHeight) bis 250 × 200 dp (maxResizeHeight).

Ihr Widget muss den Größenbereich von minResizeWidth × minResizeHeight bis maxResizeWidth × maxResizeHeight unterstützen. Innerhalb dieses Bereichs können Sie den Grenzwert für den Layoutwechsel festlegen.

Beispiel für ein responsives Layout
Abbildung 1. Beispiel für ein responsives Layout

Genaue Layouts angeben

Wenn eine kleine Anzahl responsiver Layouts nicht möglich ist, können Sie stattdessen verschiedene Layouts bereitstellen, die auf die Größen zugeschnitten sind, in denen das Widget angezeigt wird. Das sind in der Regel zwei Größen für Smartphones (Hoch- und Querformat) und vier Größen für faltbare Geräte.

Um diese Lösung zu implementieren, muss Ihre App die folgenden Schritte ausführen:

  1. „Überladen“ AppWidgetProvider.onAppWidgetOptionsChanged(), das aufgerufen wird, wenn sich die Größen ändern.

  2. Rufen Sie AppWidgetManager.getAppWidgetOptions() auf. Dadurch wird ein Bundle mit den Größen zurückgegeben.

  3. Rufen Sie den Schlüssel AppWidgetManager.OPTION_APPWIDGET_SIZES über das Bundle auf.

Das folgende Codebeispiel zeigt, wie Sie genaue Layouts angeben.

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) { }

Größe für das Widget festlegen

Für jedes Widget müssen targetCellWidth und targetCellHeight für Geräte mit Android 12 oder höher bzw. minWidth und minHeight für alle Android-Versionen definiert werden, um anzugeben, wie viel Speicherplatz standardmäßig mindestens verbraucht. Wenn Nutzer jedoch ihrem Startbildschirm ein Widget hinzufügen, nimmt es in der Regel mehr als die von Ihnen angegebene Mindestbreite und -höhe ein.

Android-Startbildschirme bieten Nutzern ein Raster mit verfügbaren Bereichen, in die sie Widgets und Symbole einfügen können. Dieses Raster kann je nach Gerät variieren. Viele Smartphones bieten beispielsweise ein Raster von 5 × 4 an, während Tablets ein größeres Raster haben können. Wenn das Widget hinzugefügt wird, wird es horizontal und vertikal so gedehnt, dass es die Mindestanzahl an Zellen einnimmt, die für die Einschränkungen für targetCellWidth und targetCellHeight auf Geräten mit Android 12 oder höher oder für die Einschränkungen für minWidth und minHeight auf Geräten mit Android 11 (API-Level 30) oder niedriger erforderlich sind.

Sowohl die Breite und Höhe einer Zelle als auch die Größe der automatischen Ränder, die auf Widgets angewendet werden, können je nach Gerät variieren. Anhand der folgenden Tabelle können Sie die Mindestabmessungen Ihres Widgets auf einem typischen Smartphone mit einem 5 × 4-Raster grob abschätzen, je nach Anzahl der belegten Rasterzellen:

Anzahl der Zellen (Breite x Höhe) Verfügbare Größe im Porträtmodus (dp) Verfügbare Größe im Querformat (dp)
1:1 57 × 102 dp 127x51dp
2x1 130 × 102 dp 269x51dp
3x1 203 × 102 dp 412 × 51 dp
4x1 276 × 102 dp 554x51dp
5x1 349x102dp 697x51dp
5x2 349 × 220 dp 697 × 117 dp
5x3 349 × 337 dp 697x184dp
5x4 349 × 455 dp 697 × 250 dp
n × m (73n – 16) × (118m – 16) (142n – 15) × (66m – 15)

Verwenden Sie die Zellengrößen im Porträtmodus, um die Werte für die Attribute minWidth, minResizeWidth und maxResizeWidth anzugeben. Verwenden Sie die Zellengrößen im Querformat, um die Werte für die Attribute minHeight, minResizeHeight und maxResizeHeight festzulegen.

Der Grund dafür ist, dass die Zellenbreite im Hochformat in der Regel kleiner als im Querformat ist und entsprechend kleiner im Querformat als im Hochformat ist.

Wenn du beispielsweise möchtest, dass die Größe des Widgets auf einem Google Pixel 4 bis zu einer Zelle verkleinert werden kann, musst du minResizeWidth auf höchstens 56 dp festlegen. Dadurch wird sichergestellt, dass der Wert für das Attribut minResizeWidth kleiner als 57 dp ist, da eine Zelle im Hochformat mindestens 57 dp breit ist. Wenn Sie die Höhe des Widgets in einer Zelle auf demselben Gerät ändern möchten, müssen Sie minResizeHeight auf höchstens 50 dp festlegen, damit der Wert für das minResizeHeight-Attribut kleiner als 51 dp ist. Eine Zelle ist im Querformat mindestens 51 dp hoch.

Die Größe jedes Widgets kann innerhalb der Größenbereiche zwischen den Attributen minResizeWidth/minResizeHeight und maxResizeWidth/maxResizeHeight geändert werden, d. h., es muss an alle Größenbereiche zwischen ihnen angepasst werden.

Um die Standardgröße des Widgets bei der Platzierung festzulegen, können Sie beispielsweise die folgenden Attribute festlegen:

<appwidget-provider
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

Das bedeutet, dass die Standardgröße des Widgets 3 x 2 Zellen ist, wie durch die Attribute targetCellWidth und targetCellHeight angegeben, oder 180 x 110 dp, wie durch minWidth und minHeight für Geräte mit Android 11 oder niedriger angegeben. Im letzteren Fall kann die Größe in Zellen je nach Gerät variieren.

Mit den folgenden Attributen können Sie die unterstützten Größenbereiche Ihres Widgets festlegen:

<appwidget-provider
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

Wie durch die vorherigen Attribute angegeben, kann die Breite des Widgets von 180 dp auf 530 dp und die Höhe von 110 dp auf 450 dp skaliert werden. Die Größe des Widgets kann dann von 3 x 2 in 5 x 2-Zellen geändert werden, sofern die folgenden Bedingungen erfüllt sind:

  • Das Gerät hat das Raster 5 × 4.
  • Die Zuordnung zwischen der Anzahl der Zellen und der verfügbaren Größe in dps entspricht der Tabelle mit Schätzungen der Mindestabmessungen auf dieser Seite.
  • Das Widget passt sich an diesen Größenbereich an.

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);

Angenommen, das Widget verwendet die responsiven Layouts, die in den vorherigen Code-Snippets definiert wurden. Das Layout, das als R.layout.widget_weather_forecast_small angegeben ist, wird also von 180 × 110 dp (minResizeWidth × minResizeHeight) bis 269 × 279 dp (nächste Grenzwerte – 1) verwendet. Ebenso wird R.layout.widget_weather_forecast_medium von 270 × 110 dp bis 270 × 279 dp und R.layout.widget_weather_forecast_large von 270 × 280 dp bis 530 dp (maxResizeWidth) × 450 dp (maxResizeHeight) verwendet.

Wenn der Nutzer die Größe des Widgets ändert, ändert sich sein Erscheinungsbild, um sich an die jeweilige Zellengröße anzupassen, wie in den folgenden Beispielen gezeigt.

Beispiel für ein Wetter-Widget im kleinsten 3 × 2-Raster Auf der Benutzeroberfläche sind der Ortsname (Tokio), die Temperatur (14 °C) und ein Symbol für bewölktes Wetter zu sehen.
Abbildung 2. 3 × 2 R.layout.widget_weather_forecast_small.

Beispiel für ein Wetter-Widget in der Größe „mittel“ (4 × 2). Wenn Sie das Widget auf diese Weise neu skalieren, wird die gesamte Benutzeroberfläche der vorherigen Widget-Größe verwendet und das Label „Etwas bewölkt“ sowie eine Temperaturvorhersage von 16:00 bis 19:00 Uhr hinzugefügt.
Abbildung 3. 4 × 2 R.layout.widget_weather_forecast_medium.

Beispiel für ein Wetter-Widget in der Größe „mittel“ (5 × 2). Wenn Sie das Widget so vergrößern, bleibt die Benutzeroberfläche gleich wie bei der vorherigen Größe, sie wird jedoch um eine Zellenlänge gedehnt, um mehr horizontalen Platz einzunehmen.
Abbildung 4. 5 × 2 R.layout.widget_weather_forecast_medium.

Beispiel für ein Wetter-Widget in der Größe „5 × 3“ (groß). Wenn Sie die Größe des Widgets auf diese Weise ändern, wird die gesamte Benutzeroberfläche der vorherigen Widget-Größen verwendet und es wird eine Ansicht im Widget hinzugefügt, die eine Vorhersage für Dienstag und Mittwoch enthält. Symbole für sonniges oder regnerisches Wetter sowie Höchst- und Tiefsttemperaturen für jeden Tag.
Abbildung 5. 5 × 3 R.layout.widget_weather_forecast_large.

Beispiel für ein Wetter-Widget im Format 5 x 4 „Large“ (L). Wenn Sie die Größe des Widgets so ändern, wird die gesamte Benutzeroberfläche der vorherigen Widget-Größen verwendet und Donnerstag und Freitag (sowie die entsprechenden Symbole für die Wetterlage sowie die Höchst- und Tiefsttemperaturen für jeden Tag) werden hinzugefügt.
Abbildung 6. 5x4 R.layout.widget_weather_forecast_large.