Responsives/adaptives Design mit Ansichten

Responsive/adaptive Layouts sorgen unabhängig von der Bildschirmgröße für eine optimierte Nutzererfahrung. Implementieren Sie responsive/adaptive Layouts, damit Ihre ansichtsbasierte App alle Bildschirmgrößen, -ausrichtungen und -konfigurationen unterstützt, einschließlich Konfigurationen mit anpassbarer Größe wie dem Mehrfenstermodus.

Responsives Design

Der erste Schritt zur Unterstützung einer Vielzahl von Geräteformfaktoren besteht darin, ein Layout zu erstellen, das auf Variationen des für Ihre App verfügbaren Anzeigeraums reagiert.

ConstraintLayout

Am besten erstellen Sie ein responsives Layout mit ConstraintLayout als Basislayout für Ihre UI. Mit ConstraintLayout können Sie die Position und Größe jeder Ansicht entsprechend den räumlichen Beziehungen zu anderen Ansichten im Layout angeben. Alle Ansichten können dann zusammen verschoben und vergrößert werden, wenn sich der Anzeigebereich ändert.

Am einfachsten lässt sich ein Layout mit ConstraintLayout mit dem Layout-Editor in Android Studio erstellen. Mit dem Layout-Editor können Sie neue Ansichten in das Layout ziehen, Einschränkungen relativ zu übergeordneten und gleichgeordneten Ansichten anwenden und Ansichtseigenschaften festlegen – ohne XML von Hand bearbeiten zu müssen.

Abbildung 3: Der Layout-Editor in Android Studio mit ConstraintLayout.

Weitere Informationen finden Sie unter Responsive UI mit ConstraintLayout erstellen.

Responsive Breite und Höhe

Damit Ihr Layout an unterschiedliche Bildschirmgrößen angepasst wird, verwenden Sie wrap_content, match_parent oder 0dp (match constraint) für die Breite und Höhe von Ansichtskomponenten anstelle von hartcodierten Werten:

  • wrap_content: Die Größe der Ansicht wird so festgelegt, dass sie in den Inhalt der Ansicht passt.
  • match_parent: Die Ansicht wird innerhalb der übergeordneten Ansicht so weit wie möglich erweitert.
  • 0dp (match constraint): In einem ConstraintLayout, ähnlich wie bei match_parent. Die Ansicht nimmt den gesamten verfügbaren Platz innerhalb der Einschränkungen der Ansicht ein.

Beispiele:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/lorem_ipsum" />

In Abbildung 4 sehen Sie, wie Breite und Höhe des TextView angepasst werden, wenn sich die Breite des Bildschirms mit der Ausrichtung des Geräts ändert.

Abbildung 4: Ein responsives TextView.

Die Breite (TextView) füllt den gesamten verfügbaren Platz aus (match_parent) und entspricht genau der Höhe des enthaltenen Textes (wrap_content). Dadurch kann die Ansicht an verschiedene Anzeigeabmessungen und verschiedene Textmengen angepasst werden.

Wenn Sie eine LinearLayout verwenden, können Sie die untergeordneten Ansichten auch basierend auf der Layoutstärke erweitern, sodass die Ansichten den verfügbaren Platz proportional ausfüllen. Wenn Sie jedoch Gewichtungen in einem verschachtelten LinearLayout verwenden, muss das System mehrere Layoutdurchläufe ausführen, um die Größe für jede Ansicht zu bestimmen. Dies beeinträchtigt die Leistung der UI.

ConstraintLayout kann fast alle mit LinearLayout möglichen Layouts erstellen, ohne dass sich dies auf die Leistung auswirkt. Wandeln Sie das verschachtelte LinearLayout-Objekt in ConstraintLayout um. Anschließend können Sie gewichtete Layouts mit Einschränkungsketten definieren.

Adaptives Design

Das Layout Ihrer App sollte immer an verschiedene Bildschirmgrößen angepasst werden. Allerdings kann selbst ein responsives Layout nicht auf allen Geräten oder im Mehrfenstermodus die beste Nutzererfahrung bieten. Beispielsweise bietet die Benutzeroberfläche, die Sie für ein Smartphone entworfen haben, auf einem Tablet wahrscheinlich keine optimale Nutzererfahrung. Mit adaptivem Design stehen alternative Layouts zur Verfügung, die für verschiedene Displayabmessungen optimiert sind.

SlidingPaneLayout für Benutzeroberflächen mit Listendetails

Eine Benutzeroberfläche mit Listendetails bietet in der Regel auf Bildschirmen unterschiedlicher Größe eine unterschiedliche User Experience. Auf großen Bildschirmen sind Listen- und Detailbereiche in der Regel nebeneinander. Wenn ein Element in der Liste ausgewählt wird, werden die Elementinformationen im Detailbereich ohne Änderung der Benutzeroberfläche angezeigt. Die beiden Bereiche bleiben nebeneinander. Auf kleinen Bildschirmen werden die beiden Bereiche jedoch separat angezeigt, wobei jeder Bereich den gesamten Anzeigebereich einnimmt. Wird ein Element im Listenbereich ausgewählt, ersetzt der Detailbereich (mit den Informationen zum ausgewählten Element) den Listenbereich. Die Zurück-Navigation ersetzt den Detailbereich durch die Liste.

SlidingPaneLayout verwaltet die Logik, um zu bestimmen, welche der beiden Nutzererfahrungen für die aktuelle Fenstergröße geeignet ist:

<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/item_navigation" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Die Attribute layout_width und layout_weight der beiden in SlidingPaneLayout enthaltenen Ansichten bestimmen das SlidingPaneLayout-Verhalten. Wenn das Fenster in diesem Beispiel groß genug ist (mindestens 580 dp breit), um beide Ansichten anzuzeigen, werden die Bereiche nebeneinander angezeigt. Ist die Fensterbreite jedoch kleiner als 580 dp, werden die Bereiche übereinander geschoben, um einzeln das gesamte App-Fenster einzunehmen.

Ist die Fensterbreite größer als die angegebene Mindestbreite (580 dp), können layout_weight-Werte verwendet werden, um die Größe der beiden Fenster proportional zu skalieren. Im Beispiel ist der Listenbereich immer 280 dp breit, da er keine Gewichtung hat. Aufgrund der Einstellung layout_weight der Ansicht füllt der Detailbereich jedoch immer horizontale Flächen über 580 dp aus.

Ressourcen für alternatives Layout

Wenn Sie das UI-Design an stark variierende Anzeigegrößen anpassen möchten, verwenden Sie alternative Layouts, die durch Ressourcenqualifizierer identifiziert werden.

Abbildung 5: Dieselbe App verwendet unterschiedliche Layouts für unterschiedliche Displaygrößen.

Sie können adaptive, bildschirmspezifische Layouts bereitstellen, indem Sie im Quellcode Ihrer App zusätzliche res/layout/-Verzeichnisse erstellen. Erstellen Sie ein Verzeichnis für jede Bildschirmkonfiguration, die ein anderes Layout erfordert. Hängen Sie dann einen Bildschirmkonfigurations-Qualifier an den layout-Verzeichnisnamen an (z. B. layout-w600dp für Bildschirme mit einer verfügbaren Breite von 600 dp).

Die Konfigurationsqualifizierer geben den sichtbaren Anzeigebereich an, der für die App-UI verfügbar ist. Das System berücksichtigt bei der Auswahl des Layouts für Ihre App alle Systemdekorationen (z. B. die Navigationsleiste) und Änderungen an der Fensterkonfiguration (z. B. der Mehrfenstermodus).

Informationen zum Erstellen alternativer Layouts in Android Studio finden Sie im Artikel UI mit Ansichten entwickeln unter Layoutvarianten zur Optimierung für verschiedene Bildschirme verwenden.

Qualifier mit kleinster Breite

Mit dem Bildschirmgrößenkennzeichner für die kleinste Breite können Sie alternative Layouts für Bildschirme mit einer Mindestbreite in dichteunabhängigen Pixeln (dp) bereitstellen.

Da die Bildschirmgröße als Maß für dp beschrieben wird, können Sie mit Android Layouts erstellen, die auf bestimmte Displayabmessungen ausgelegt sind, ohne dabei unterschiedliche Pixeldichten berücksichtigen zu müssen.

Beispielsweise können Sie ein Layout mit dem Namen main_activity erstellen, das für Smartphones und Tablets optimiert ist. Dazu erstellen Sie verschiedene Versionen der Datei in verschiedenen Verzeichnissen:

res/layout/main_activity.xml           # For phones (smaller than 600dp smallest width)
res/layout-sw600dp/main_activity.xml   # For 7" tablets (600dp wide or wider)

Der kleinste Breitenqualifizierer gibt die kleinste der beiden Seiten des Displays an, unabhängig von der aktuellen Ausrichtung des Geräts. Er ist also eine Möglichkeit, die für Ihr Layout verfügbare Gesamtanzeigegröße anzugeben.

Hier sehen Sie, wie die anderen kleinsten Breitenwerte typischen Bildschirmgrößen entsprechen:

  • 320 dp: kleiner Smartphone-Bildschirm (240 x 320 ldpi, 320 x 480 MDPI, 480 x 800 hdpi usw.)
  • 480 dp: Großer Smartphone-Bildschirm mit ca. 5 Zoll (480 x 800 MDPI)
  • 600 dp: 7"-Tablet (600 x 1024 MDPI)
  • 720 dp: 10"-Tablet (720 x 1280 MDPI, 800 x 1280 MDpi usw.)

Die folgende Abbildung zeigt eine detailliertere Darstellung, wie verschiedene Bildschirm-dp-Breiten verschiedenen Bildschirmgrößen und -ausrichtungen entsprechen.

Abbildung 6. Haltepunkte mit empfohlener Breite zur Unterstützung verschiedener Bildschirmgrößen

Die Werte für den Qualifizierer für die kleinste Breite sind dp. Es kommt darauf an, wie groß der verfügbare Anzeigebereich ist, nachdem das System die Pixeldichte berücksichtigt hat (nicht die Rohpixelauflösung).

Die Größen, die Sie mit Ressourcenkennzeichnern wie z. B. der kleinsten Breite angeben, entsprechen nicht den tatsächlichen Bildschirmgrößen. Stattdessen geben die Größen die Breite oder Höhe in dp-Einheiten an, die für das Fenster Ihrer App verfügbar sind. Das Android-System verwendet möglicherweise einen Teil des Bildschirms für die System-UI (z. B. die Systemleiste am unteren Bildschirmrand oder die Statusleiste oben), sodass ein Teil des Bildschirms für Ihr Layout möglicherweise nicht verfügbar ist. Wenn Ihre App im Mehrfenstermodus verwendet wird, hat die App nur Zugriff auf die Größe des Fensters, das die App enthält. Wenn die Größe des Fensters angepasst wird, löst dies eine Konfigurationsänderung mit der neuen Fenstergröße aus, wodurch das System eine geeignete Layoutdatei auswählen kann. Die von Ihnen deklarierten Ressourcenkennzeichnergrößen sollten daher nur den von Ihrer Anwendung benötigten Bereich angeben. Das System berücksichtigt den von der System-UI belegten Speicherplatz, wenn Platz für Ihr Layout bereitgestellt wird.

Verfügbarer Breitenkennzeichner

Anstatt das Layout basierend auf der kleinsten Bildschirmbreite zu ändern, können Sie es an die verfügbare Breite oder Höhe anpassen. Sie können beispielsweise ein Layout mit zwei Bereichen verwenden, wenn der Bildschirm eine Breite von mindestens 600 dp hat. Diese kann sich ändern, je nachdem, ob sich das Gerät im Quer- oder Hochformat befindet. In diesem Fall sollten Sie den Qualifizierer available width (verfügbare Breite) so verwenden:

res/layout/main_activity.xml         # For phones (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml  # For 7" tablets or any screen with 600dp available width
                                     # (possibly landscape phones)

Wenn die verfügbare Höhe für Ihre App ein Problem darstellt, können Sie den Qualifizierer available_height verwenden. Beispiel: layout-h600dp für Bildschirme mit einer Bildschirmhöhe von mindestens 600 dp.

Ausrichtungsqualifizierer

Auch wenn Sie möglicherweise alle Größenvariationen unterstützen können, wenn Sie nur die Qualifier für die kleinste Breite und die verfügbare Breite verwenden, möchten Sie vielleicht auch die Nutzererfahrung ändern, wenn der Nutzer zwischen Hoch- und Querformat wechselt.

Dazu können Sie den Namen des Layoutverzeichnisses die Qualifier port oder land hinzufügen. Achten Sie aber darauf, dass die Ausrichtungskennzeichner nach den Größenkennzeichnern folgen. Beispiele:

res/layout/main_activity.xml                # For phones
res/layout-land/main_activity.xml           # For phones in landscape
res/layout-sw600dp/main_activity.xml        # For 7" tablets
res/layout-sw600dp-land/main_activity.xml   # For 7" tablets in landscape

Weitere Informationen zu allen Qualifier für die Bildschirmkonfiguration finden Sie in der Übersicht über Anwendungsressourcen.

Fenstergrößenklassen

Fenstergrößenklassen sind Haltepunkte für den Darstellungsbereich, mit denen Sie adaptive Layouts erstellen können. Die Haltepunkte geben den Anzeigebereich an, der der Anwendung als kompakt, mittel oder erweitert zur Verfügung steht. Breite und Höhe werden separat angegeben. Daher hat Ihre App immer eine Fenstergrößenklasse für die Breite und eine Fenstergrößenklasse für die Höhe.

So wenden Sie adaptive Layouts programmatisch an:

  • Layoutressourcen basierend auf den Haltepunkten der Fenstergrößenklasse erstellen
  • Berechnen Sie die Fenstergrößenklassen für die Breite und Höhe Ihrer App mit der Funktion WindowSizeClass#compute() aus der Bibliothek Jetpack WindowManager.
  • Layout-Ressource für die aktuellen Fenstergrößenklassen aufblähen

Weitere Informationen zu Fenstergrößenklassen finden Sie unter Unterstützung verschiedener Bildschirmgrößen.

Modularisierte UI-Komponenten mit Fragmenten

Wenn Sie Ihre App für mehrere Anzeigegrößen entwerfen, sollten Sie die UI-Logik mithilfe von Fragmenten in separate Komponenten extrahieren. So sorgen Sie dafür, dass das UI-Verhalten nicht unnötig bei verschiedenen Aktivitäten dupliziert wird. Anschließend können Sie Fragmente kombinieren, um Layouts mit mehreren Bereichen auf großen Bildschirmen zu erstellen, oder Fragmente in separaten Aktivitäten auf kleinen Bildschirmen platzieren.

Beispielsweise könnte das Muster mit den Listendetails (siehe SlidingPaneLayout oben) so implementiert werden, dass ein Fragment die Liste und ein anderes die Details der Listenelemente enthält. Auf großen Bildschirmen könnten die Fragmente nebeneinander angezeigt werden, auf kleinen Bildschirmen einzeln und als Füllung.

Weitere Informationen finden Sie in der Übersicht zu Fragmenten.

Einbetten von Aktivitäten

Wenn Ihre App aus mehreren Aktivitäten besteht, können Sie mithilfe der Aktivitätseinbettung ganz einfach eine adaptive UI erstellen.

Bei der Aktivitätseinbettung werden mehrere Aktivitäten oder mehrere Instanzen derselben Aktivität gleichzeitig im Aufgabenfenster einer Anwendung angezeigt. Auf großen Bildschirmen können Aktivitäten nebeneinander angezeigt werden, auf kleinen Bildschirmen übereinander.

Sie legen fest, wie Ihre Anwendung ihre Aktivitäten anzeigt. Dazu erstellen Sie eine XML-Konfigurationsdatei, mit der das System die geeignete Darstellung basierend auf der Anzeigegröße bestimmt. Alternativ können Sie Jetpack WindowManager API-Aufrufe ausführen.

Das Einbetten von Aktivitäten unterstützt das Ändern der Geräteausrichtung und faltbare Geräte sowie das Stapeln und Auflösen von Aktivitäten, wenn das Gerät gedreht, auf- und zugeklappt wird.

Weitere Informationen finden Sie unter Aktivitätseinbettung.

Bildschirmgrößen und Seitenverhältnisse

Testen Sie Ihre App mit verschiedenen Bildschirmgrößen und Seitenverhältnissen, um sicherzustellen, dass Ihre UI richtig skaliert wird.

Android 10 (API-Level 29) und höher unterstützen viele verschiedene Seitenverhältnisse. Faltbare Formfaktoren können von großen, schmalen Bildschirmen (z. B. 21:9 im zusammengeklappten Format) bis hin zu einem quadratischen Seitenverhältnis von 1:1 (aufgeklappt) variieren.

Damit die Apps mit so vielen Geräten wie möglich kompatibel sind, solltest du sie auf möglichst viele der folgenden Bildschirmseitenverhältnisse testen:

Abbildung 7. Verschiedene Seitenverhältnisse für das Display.

Wenn Sie keinen Zugriff auf Geräte für die verschiedenen Bildschirmgrößen haben, die Sie testen möchten, können Sie mit dem Android-Emulator nahezu jede Bildschirmgröße emulieren.

Wenn Sie den Test lieber auf einem echten Gerät durchführen möchten, das Gerät aber nicht haben, können Sie mit dem Firebase Test Lab auf Geräte in einem Google-Rechenzentrum zugreifen.

Weitere Informationen