Kochbuch für große Bildschirme

Android bietet alle Zutaten für 5-Sterne-Apps für große Bildschirme. Bei den Rezepten in diesem Kochbuch werden ausgewählte Zutaten ausgewählt und kombiniert, um bestimmte Entwicklungsprobleme zu lösen. Jedes Rezept enthält Best Practices, hochwertige Codebeispiele und Schritt-für-Schritt-Anleitungen, mit denen du ein Top-Koch auf dem großen Bildschirm wirst.

Bewertungen

Die Rezepte werden mit Sternen bewertet, je nachdem, wie gut sie den Qualitätsrichtlinien für Apps mit großen Bildschirmen entsprechen.

Fünf-Sterne-Bewertung Erfüllt die Kriterien für Tier 1, unterscheidet sich von großem Bildschirm
Vier-Sterne-Bewertung Erfüllt die Kriterien für Tier 2, für große Bildschirme optimiert
3-Sterne-Bewertung Erfüllt die Kriterien für Tier 3, großer Bildschirm bereit
Bewertung mit zwei Sternen Bietet einige Funktionen für große Bildschirme, erfüllt jedoch nicht die Qualitätsrichtlinien für Apps mit großen Bildschirmen
Bewertung mit einem Stern Erfüllt die Anforderungen eines bestimmten Anwendungsfalls, unterstützt aber keine großen Bildschirme richtig

Chromebook-Kameraunterstützung

3-Sterne-Bewertung

Machen Sie Chromebook-Nutzer bei Google Play auf sich aufmerksam.

Wenn Ihre Kamera-App nur mit grundlegenden Kamerafunktionen funktioniert, sollten App-Shops Chromebook-Nutzer nicht daran hindern, die App zu installieren, nur weil Sie versehentlich erweiterte Kamerafunktionen von High-End-Smartphones angegeben haben.

Chromebooks haben eine eingebaute Frontkamera (für Nutzer sichtbar), die sich gut für Videokonferenzen, Momentaufnahmen und andere Anwendungen eignet. Allerdings haben nicht alle Chromebooks eine rückseitige Kamera (mit Blick auf die Welt) und die meisten Chromebook-Kameras für Nutzer unterstützen weder Autofokus noch den Blitz.

Best Practices

Vielseitige Kamera-Apps unterstützen alle Geräte unabhängig von der Kamerakonfiguration – Geräte mit Frontkameras, Rückkameras und über USB angeschlossene externe Kameras.

Damit App-Shops Ihre App für möglichst viele Geräte verfügbar machen, sollten Sie immer alle von Ihrer App verwendeten Kamerafunktionen angeben und explizit angeben, ob sie erforderlich sind.

Zutaten

  • Berechtigung CAMERA: Ermöglicht deiner App den Zugriff auf die Kameras eines Geräts
  • <uses-feature>-Manifestelement: In App-Shops werden die von Ihrer App verwendeten Funktionen informiert.
  • Attribut required: Gibt für App-Shops an, ob Ihre App auch ohne eine bestimmte Funktion funktionieren kann

Schritte

Zusammenfassung

Deklarieren Sie die Berechtigung CAMERA. Deklarieren Sie Kamerafunktionen, die eine grundlegende Kameraunterstützung bieten. Geben Sie an, ob die einzelnen Funktionen erforderlich sind.

1. Deklarieren Sie die Berechtigung CAMERA

Füge dem App-Manifest die folgende Berechtigung hinzu:

<uses-permission android:name="android.permission.CAMERA" />
2. Grundlegende Kamerafunktionen deklarieren

Fügen Sie dem App-Manifest die folgenden Funktionen hinzu:

<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
3. Angeben, ob die einzelnen Funktionen erforderlich sind

Lege „android:required="false"“ für die Funktion „android.hardware.camera.any“ fest, damit Geräte mit einer integrierten oder externen Kamera – oder ganz ohne Kamera – auf deine App zugreifen können.

Legen Sie für die anderen Funktionen android:required="false" fest, damit Geräte wie z. B. Chromebooks ohne Rückkamera, Autofokus und Blitz Ihre App im App-Shop aufrufen können.

Ergebnis

Chromebook-Nutzer können Ihre App bei Google Play und anderen App-Shops herunterladen und installieren. Bei Geräten mit vollwertiger Kameraunterstützung, z. B. Smartphones, gelten keine Einschränkungen in Bezug auf die Kamerafunktion.

Durch die explizite Einstellung der von Ihrer App unterstützten Kamerafunktionen und die Angabe der Funktionen, die Ihre App benötigt, haben Sie Ihre App für möglichst viele Geräte verfügbar gemacht.

Zusätzliche Ressourcen

Weitere Informationen finden Sie unter Kamerahardwarefunktionen in der <uses-feature>-Dokumentation.

App-Ausrichtung auf Smartphones, aber nicht auf Geräten mit großen Bildschirmen eingeschränkt

Bewertung mit zwei Sternen

Ihre App funktioniert gut auf Smartphones im Hochformat, daher haben Sie die App auf das Hochformat beschränkt. Aber Sie sehen die Chance, auf großen Bildschirmen im Querformat mehr zu erreichen.

Wie lässt sich das erreichen? Beschränken Sie die App auf das Hochformat für kleine Bildschirme und aktivieren Sie das Querformat auf großen Bildschirmen?

Best Practices

Die besten Apps berücksichtigen Nutzerpräferenzen wie die Geräteausrichtung.

In den Qualitätsrichtlinien für Apps mit großen Bildschirmen wird empfohlen, dass Apps alle Gerätekonfigurationen unterstützen, einschließlich Hoch- und Querformat, Mehrfenstermodus sowie auf- und zugeklappten Geräten. Apps sollten Layouts und Benutzeroberflächen für verschiedene Konfigurationen optimieren und Apps sollten den Status bei Konfigurationsänderungen speichern und wiederherstellen.

Dieses Rezept ist nur eine vorübergehende Maßnahme – Unterstützung für große Bildschirme. Verwende das Schema, bis du deine App verbessern kannst, um vollständige Unterstützung für alle Gerätekonfigurationen bereitzustellen.

Zutaten

  • screenOrientation: In der App-Manifest-Einstellung kannst du angeben, wie deine App auf Änderungen der Geräteausrichtung reagieren soll
  • Jetpack WindowManager: Satz von Bibliotheken, mit denen Sie die Größe und das Seitenverhältnis des App-Fensters bestimmen können; abwärtskompatibel zu API-Level 14
  • Activity#setRequestedOrientation(): Methode, mit der Sie die Ausrichtung der App während der Laufzeit ändern können

Schritte

Zusammenfassung

Sie können festlegen, dass die App standardmäßig die Ausrichtungsänderungen im App-Manifest verarbeiten kann. Bestimmen Sie während der Laufzeit die Größe des App-Fensters. Wenn das App-Fenster klein ist, können Sie die Ausrichtung der App einschränken, indem Sie die Einstellung für die Manifestausrichtung überschreiben.

1. Ausrichtungseinstellung im App-Manifest angeben

Sie können entweder die Deklaration des Elements screenOrientation des App-Manifests vermeiden und die Bildschirmausrichtung auf fullUser festlegen. In diesem Fall ist die Ausrichtung standardmäßig auf unspecified festgelegt. Wenn der Nutzer die sensorbasierte Rotation nicht gesperrt hat, unterstützt deine App alle Geräteausrichtungen.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

Der Unterschied zwischen unspecified und fullUser ist subtil, aber wichtig. Wenn du keinen screenOrientation-Wert angibst, wählt das System die Ausrichtung aus. Die vom System zur Definition der Ausrichtung verwendete Richtlinie kann sich von Gerät zu Gerät unterscheiden. Andererseits entspricht die Angabe von fullUser eher dem Verhalten, das der Nutzer für das Gerät definiert hat: Wenn der Nutzer die sensorbasierte Drehung aktiviert hat, folgt die App den Präferenzen des Nutzers. Andernfalls lässt das System jede der vier möglichen Bildschirmausrichtungen zu (Hochformat, Querformat, umgekehrtes Hochformat oder umgekehrtes Querformat). Weitere Informationen finden Sie unter android:screenOrientation.

2. Bildschirmgröße bestimmen

Wenn das Manifest so festgelegt ist, dass alle von Nutzern zulässigen Ausrichtungen unterstützt werden, können Sie die Ausrichtung der App programmatisch basierend auf der Bildschirmgröße angeben.

Fügen Sie die Jetpack WindowManager-Bibliotheken der build.gradle- oder build.gradle.kts-Datei des Moduls hinzu:

Kotlin

implementation("androidx.window:window:version")
implementation("androidx.window:window-core:version")

Cool

implementation 'androidx.window:window:version'
implementation 'androidx.window:window-core:version'

Verwenden Sie die Methode Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics(), um die Bildschirmgröße des Geräts als WindowMetrics-Objekt abzurufen. Die Fenstermesswerte können mit Fenstergrößenklassen verglichen werden, um zu entscheiden, wann die Ausrichtung eingeschränkt werden soll.

Windows-Größenklassen stellen die Haltepunkte zwischen kleinen und großen Bildschirmen bereit.

Verwenden Sie die Haltepunkte WindowWidthSizeClass#COMPACT und WindowHeightSizeClass#COMPACT, um die Bildschirmgröße zu bestimmen:

Kotlin

/** Determines whether the device has a compact screen. **/
fun compactScreen() : Boolean {
    val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
    val width = metrics.bounds.width()
    val height = metrics.bounds.height()
    val density = resources.displayMetrics.density
    val windowSizeClass = WindowSizeClass.compute(width/density, height/density)

    return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT ||
        windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT
}

Java

/** Determines whether the device has a compact screen. **/
private boolean compactScreen() {
    WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this);
    int width = metrics.getBounds().width();
    int height = metrics.getBounds().height();
    float density = getResources().getDisplayMetrics().density;
    WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density);
    return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT ||
                windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT;
}
    Hinweis:
  • Die obigen Beispiele werden als Methoden einer Aktivität implementiert. Daher wird die Aktivität im Argument von computeMaximumWindowMetrics() als this dereferenziert.
  • Die Methode computeMaximumWindowMetrics() wird anstelle von computeCurrentWindowMetrics() verwendet, da die App im Mehrfenstermodus gestartet werden kann. In diesem Fall wird die Einstellung für die Bildschirmausrichtung ignoriert. Es macht keinen Sinn, die Größe des App-Fensters zu bestimmen und die Ausrichtungseinstellung zu überschreiben, es sei denn, das App-Fenster ist der gesamte Gerätebildschirm.

Eine Anleitung zum Deklarieren von Abhängigkeiten finden Sie unter WindowManager, um die Methode computeMaximumWindowMetrics() in Ihrer App verfügbar zu machen.

3. App-Manifest-Einstellung überschreiben

Wenn Sie festgestellt haben, dass das Gerät über eine kompakte Bildschirmgröße verfügt, können Sie Activity#setRequestedOrientation() aufrufen, um die screenOrientation-Einstellung des Manifests zu überschreiben:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requestedOrientation = if (compactScreen())
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    ...
    // Replace with a known container that you can safely add a
    // view to where the view won't affect the layout and the view
    // won't be replaced.
    val container: ViewGroup = binding.container

    // Add a utility view to the container to hook into
    // View.onConfigurationChanged. This is required for all
    // activities, even those that don't handle configuration
    // changes. You can't use Activity.onConfigurationChanged,
    // since there are situations where that won't be called when
    // the configuration changes. View.onConfigurationChanged is
    // called in those scenarios.
    container.addView(object : View(this) {
        override fun onConfigurationChanged(newConfig: Configuration?) {
            super.onConfigurationChanged(newConfig)
            requestedOrientation = if (compactScreen())
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
                ActivityInfo.SCREEN_ORIENTATION_FULL_USER
        }
    })
}

Java

@Override
protected void onCreate(Bundle savedInstance) {
    super.onCreate(savedInstanceState);
    if (compactScreen()) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
    }
    ...
    // Replace with a known container that you can safely add a
    // view to where the view won't affect the layout and the view
    // won't be replaced.
    ViewGroup container = binding.container;

    // Add a utility view to the container to hook into
    // View.onConfigurationChanged. This is required for all
    // activities, even those that don't handle configuration
    // changes. You can't use Activity.onConfigurationChanged,
    // since there are situations where that won't be called when
    // the configuration changes. View.onConfigurationChanged is
    // called in those scenarios.
    container.addView(new View(this) {
        @Override
        protected void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            if (compactScreen()) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
            }
        }
    });
}

Durch Hinzufügen der Logik zu den Methoden onCreate() und View.onConfigurationChanged() können Sie die Messwerte für die maximale Fenstergröße abrufen und die Ausrichtungseinstellung überschreiben, wenn die Größe der Aktivität geändert wird oder zwischen Bildschirmen bewegt wird, beispielsweise nach dem Drehen des Geräts oder wenn ein faltbares Gerät auf- oder zugeklappt wird. Weitere Informationen dazu, wann Konfigurationsänderungen auftreten und wann sie zur Wiederherstellung von Aktivitäten führen, finden Sie unter Umgang mit Konfigurationsänderungen.

Ergebnis

Ihre App sollte jetzt auf kleinen Bildschirmen unabhängig von der Gerätedrehung im Hochformat angezeigt werden. Auf großen Bildschirmen sollte die App sowohl das Quer- als auch das Hochformat unterstützen.

Zusätzliche Ressourcen

Hilfe zum Upgrade deiner App, damit alle Gerätekonfigurationen immer unterstützt werden, findest du hier:

Medienwiedergabe mit Leertaste auf externer Tastatur pausieren und fortsetzen

Vier-Sterne-Bewertung

Die Optimierung für große Bildschirme ermöglicht die Verarbeitung externer Tastatureingaben, z. B. wenn auf die Leertaste reagiert, um die Wiedergabe von Videos und anderen Medien anzuhalten oder fortzusetzen. Dies ist besonders nützlich für Tablets, die oft an externe Tastaturen angeschlossen werden, und für Chromebooks, die normalerweise eine externe Tastatur haben, aber im Tabletmodus verwendet werden können.

Wenn Medien das einzige Element des Fensters sind (z. B. die Videowiedergabe im Vollbildmodus), reagieren Sie auf Tastendruckereignisse auf Aktivitätsebene oder in Jetpack Compose auf Bildschirmebene.

Best Practices

Wenn in Ihrer App eine Mediendatei wiedergegeben wird, sollten Nutzer die Möglichkeit haben, die Wiedergabe durch Drücken der Leertaste auf einer physischen Tastatur zu pausieren und fortzusetzen.

Zutaten

Schreiben

  • onPreviewKeyEvent: Modifier, mit dem eine Komponente Hardwareschlüsselereignisse abfangen kann, wenn sie oder eines ihrer untergeordneten Elemente im Fokus sind.
  • onKeyEvent: Ähnlich wie onPreviewKeyEvent ermöglicht diese Modifier eine Komponente, Hardwareschlüsselereignisse abzufangen, wenn sie oder eines ihrer untergeordneten Elemente im Fokus sind.

Aufrufe

  • onKeyUp(): Wird aufgerufen, wenn ein Schlüssel freigegeben und nicht von einer Ansicht innerhalb einer Aktivität verarbeitet wird.

Schritte

Zusammenfassung

Ansichtsbasierte Apps und Apps, die auf Jetpack Compose basieren, reagieren auf ähnliche Weise auf Tastatureingaben: Die App muss auf Tastendruckereignisse warten, diese filtern und auf ausgewählte Tastendrücke wie Leertaste reagieren.

1. Auf Tastaturereignisse warten

Aufrufe

Überschreiben Sie in einer Aktivität in Ihrer App die Methode onKeyUp():

Kotlin

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    ...
}

Java

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    ...
}

Die Methode wird jedes Mal aufgerufen, wenn eine gedrückte Taste losgelassen wird, sodass sie bei jedem Tastenanschlag genau einmal ausgelöst wird.

Schreiben

Mit Jetpack Compose können Sie entweder den onPreviewKeyEvent- oder onKeyEvent-Modifikator auf dem Bildschirm verwenden, der den Tastenanschlag verwaltet:

Column(modifier = Modifier.onPreviewKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp) {
        ...
    }
    ...
})

oder

Column(modifier = Modifier.onKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp) {
        ...
    }
    ...
})

2. Leertaste filtern

Filtern Sie in den Modifikatormethoden onKeyUp() oder Schreiben onPreviewKeyEvent und onKeyEvent nach KeyEvent.KEYCODE_SPACE, um das richtige Ereignis an Ihre Medienkomponente zu senden:

Aufrufe

Kotlin

if (keyCode == KeyEvent.KEYCODE_SPACE) {
    togglePlayback()
    return true
}
return false

Java

if (keyCode == KeyEvent.KEYCODE_SPACE) {
    togglePlayback();
    return true;
}
return false;

Schreiben

Column(modifier = Modifier.onPreviewKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
        ...
    }
    ...
})

oder

Column(modifier = Modifier.onKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
        ...
    }
    ...
})

Ergebnis

Deine App kann jetzt auf das Drücken der Leertaste reagieren, um ein Video oder andere Medien zu pausieren oder fortzusetzen.

Zusätzliche Ressourcen

Weitere Informationen zu Tastaturereignissen und deren Verwaltung finden Sie unter Tastatureingaben verarbeiten.

Ablehnung der Handfläche mit Eingabestift

Fünf-Sterne-Bewertung

Ein Eingabestift kann auf großen Bildschirmen ein außerordentlich produktives und kreatives Tool sein. Wenn Nutzer jedoch mit einem Eingabestift zeichnen, schreiben oder mit einer App interagieren, berühren sie den Bildschirm manchmal mit der Handfläche. Das Touch-Ereignis kann Ihrer App gemeldet werden, bevor das System es als versehentliche Berührung der Handfläche erkennt und abblendet.

Best Practices

Ihre App muss irrelevante Berührungsereignisse erkennen und ignorieren. Android bricht eine Handbewegung ab, indem ein MotionEvent-Objekt gesendet wird. Suchen Sie das Objekt für ACTION_CANCEL oder ACTION_POINTER_UP und FLAG_CANCELED, um festzustellen, ob die durch die Handflächenberührung ausgelöste Bewegung abgelehnt werden soll.

Zutaten

  • MotionEvent: Touch- und Bewegungsereignisse Enthält die Informationen, die erforderlich sind, um zu bestimmen, ob ein Ereignis ignoriert werden soll.
  • OnTouchListener#onTouch(): Empfängt MotionEvent Objekte.
  • MotionEvent#getActionMasked(): Gibt die mit einem Bewegungsereignis verknüpfte Aktion zurück
  • ACTION_CANCEL: MotionEvent-Konstante, die angibt, dass eine Geste rückgängig gemacht werden soll.
  • ACTION_POINTER_UP: MotionEvent-Konstante, die angibt, dass ein anderer Zeiger als der erste Zeiger gestiegen ist, d. h. den Kontakt mit dem Gerätebildschirm nicht mehr gegeben hat.
  • FLAG_CANCELED: MotionEvent-Konstante, die anzeigt, dass der nach oben gerichtete Zeiger ein unbeabsichtigtes Touch-Ereignis verursacht hat. Zu ACTION_POINTER_UP- und ACTION_CANCEL-Ereignissen unter Android 13 (API-Level 33) und höher hinzugefügt.

Schritte

Zusammenfassung

Untersuchen Sie die MotionEvent-Objekte, die an Ihre App gesendet wurden. Verwenden Sie die MotionEvent-APIs, um die Ereigniseigenschaften zu bestimmen:

  • Single-Pointer-Ereignisse: Prüfen Sie, ob ACTION_CANCEL vorhanden ist. Prüfen Sie unter Android 13 und höher auch, ob FLAG_CANCELED vorhanden ist.
  • Multi-Pointer-Ereignisse: Prüfen Sie unter Android 13 und höher, ob ACTION_POINTER_UP und FLAG_CANCELED vorhanden sind.

Auf „ACTION_CANCEL“ und ACTION_POINTER_UP/FLAG_CANCELED Termine antworten.

1. Bewegungsereignisobjekte abrufen

Fügen Sie Ihrer App ein OnTouchListener hinzu:

Kotlin

val myView = findViewById<View>(R.id.myView).apply {
    setOnTouchListener { view, event ->
        // Process motion event.
    }
}

Java

View myView = findViewById(R.id.myView);
myView.setOnTouchListener( (view, event) -> {
    // Process motion event.
});
2. Ereignisaktion und -meldungen festlegen

Suchen Sie nach ACTION_CANCEL. Dies weist auf ein Single-Pointer-Ereignis auf allen API-Ebenen hin. Prüfen Sie unter Android 13 und höher ACTION_POINTER_UP auf FLAG_CANCELED.

Kotlin

val myView = findViewById<View>(R.id.myView).apply {
    setOnTouchListener { view, event ->
        when (event.actionMasked) {
            MotionEvent.ACTION_CANCEL -> {
                //Process canceled single-pointer motion event for all SDK versions.
            }
            MotionEvent.ACTION_POINTER_UP -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
                   (event.flags and MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) {
                    //Process canceled multi-pointer motion event for Android 13 and higher.
                }
            }
        }
        true
    }
}

Java

View myView = findViewById(R.id.myView);
myView.setOnTouchListener( (view, event) -> {
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_CANCEL:
            // Process canceled single-pointer motion event for all SDK versions.
        case MotionEvent.ACTION_UP:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
               (event.getFlags() & MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) {
                //Process canceled multi-pointer motion event for Android 13 and higher.
            }
    }
    return true;
});
3. Bewegung rückgängig machen

Sobald Sie eine Handfläche erkannt haben, können Sie die damit verbundenen Effekte auf dem Bildschirm rückgängig machen.

In Ihrer App muss ein Verlauf der Nutzeraktionen gespeichert sein, damit unbeabsichtigte Eingaben wie Berührungen mit der Handfläche rückgängig gemacht werden können. Ein Beispiel finden Sie im Codelab Unterstützung für Eingabestifte in einer Android-App verbessern unter Einfache Zeichen-App implementieren.

Ergebnis

Deine App kann jetzt Handkontakte für Multi-Pointer-Ereignisse auf API-Ebenen mit Android 13 und höher sowie für Single-Pointer-Ereignisse auf allen API-Ebenen erkennen und ablehnen.

Zusätzliche Ressourcen

Weitere Informationen finden Sie hier:

WebView-Statusverwaltung

3-Sterne-Bewertung

WebView ist eine häufig verwendete Komponente, die ein erweitertes System für die Statusverwaltung bietet. Eine WebView muss bei Konfigurationsänderungen ihren Status beibehalten und die Scrollposition beibehalten. Ein WebView kann die Scrollposition verlieren, wenn der Nutzer das Gerät dreht oder ein faltbares Smartphone aufklappt. Dadurch muss er noch einmal vom oberen Rand des WebView zur vorherigen Scrollposition scrollen.

Best Practices

Minimieren Sie die Anzahl der Neuerstellungen von WebView. WebView ist gut in der Verwaltung des Status. Sie können diese Qualität nutzen, indem Sie so viele Konfigurationsänderungen wie möglich vornehmen. Deine App muss Konfigurationsänderungen verarbeiten, da bei der Neuerstellung von Activity (die Methode des Systems zur Verarbeitung von Konfigurationsänderungen) auch die WebView neu erstellt wird, wodurch WebView ihren Status verliert.

Zutaten

  • android:configChanges: Attribut des Manifestelements <activity>. Listet die Konfigurationsänderungen auf, die von der Aktivität verarbeitet werden.
  • View#invalidate(): Methode, die dazu führt, dass eine Ansicht neu gezeichnet wird. Übernommen von WebView.

Schritte

Zusammenfassung

Um den Status WebView zu speichern, sollten Sie nach Möglichkeit eine Neuerstellung von Activity vermeiden und dann zulassen, dass WebView entwertet wird, damit die Größe angepasst werden kann, wobei der Status beibehalten wird.

1. Konfigurationsänderungen zur AndroidManifest.xml-Datei Ihrer App hinzufügen

Vermeiden Sie die Wiederherstellung von Aktivitäten, indem Sie die Konfigurationsänderungen angeben, die von Ihrer App (und nicht vom System) verarbeitet werden:

<activity
  android:name=".MyActivity"
  android:configChanges="screenLayout|orientation|screenSize
      |keyboard|keyboardHidden|smallestScreenSize" />

2. WebView immer dann ungültig machen, wenn deine App eine Konfigurationsänderung empfängt

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    webView.invalidate()
}

Java

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    webview.invalidate();
}

Dieser Schritt gilt nur für das Ansichtssystem, da Jetpack Compose nichts ungültig machen muss, um die Größe von Composable-Elementen korrekt anzupassen. „Compose“ erstellt WebView jedoch häufig neu, wenn es nicht richtig verwaltet wird. Mit dem Accompanist WebView-Wrapper können Sie den WebView-Status in Ihren Editor-Apps speichern und wiederherstellen.

Ergebnis

Die WebView-Komponenten deiner App behalten jetzt ihren Status und ihre Scrollposition bei mehreren Konfigurationsänderungen bei, angefangen beim Ändern der Größe über das Ändern der Ausrichtung bis hin zum Aus- und Zuklappen.

Zusätzliche Ressourcen

Weitere Informationen zu Konfigurationsänderungen und deren Verwaltung finden Sie unter Umgang mit Konfigurationsänderungen.

RecyclerView-Statusverwaltung

3-Sterne-Bewertung

RecyclerView kann große Datenmengen mit minimalen grafischen Ressourcen anzeigen. Wenn RecyclerView durch die Liste der Elemente scrollt, verwendet das RecyclerView die View-Instanzen von Elementen, die außerhalb des Bildschirms gescrollt wurden, um neue Elemente zu erstellen, während diese auf dem Bildschirm scrollen. Allerdings können Konfigurationsänderungen, z. B. die Gerätedrehung, den Status eines RecyclerView zurücksetzen, sodass Nutzer wieder an ihre vorherige Position in der Liste der RecyclerView-Elemente scrollen müssen.

Best Practices

RecyclerView sollte den Status – insbesondere die Scrollposition – und den Status der Listenelemente bei allen Konfigurationsänderungen beibehalten.

Zutaten

Schritte

Zusammenfassung

Legen Sie die Richtlinie zur Statuswiederherstellung von RecyclerView.Adapter fest, um die Scrollposition RecyclerView zu speichern. Status von RecyclerView Listeneinträgen speichern. Fügen Sie dem RecyclerView-Adapter den Status der Listenelemente hinzu und stellen Sie den Status der Listenelemente wieder her, wenn sie an einen ViewHolder gebunden sind.

1. Richtlinie zur Wiederherstellung des Adapter-Status aktivieren

Aktivieren Sie die Richtlinie zur Statuswiederherstellung des RecyclerView-Adapters, damit die Scrollposition von RecyclerView bei Konfigurationsänderungen beibehalten wird. Fügen Sie dem Adapterkonstruktor die Richtlinienspezifikation hinzu:

Kotlin

class MyAdapter() : RecyclerView.Adapter() {
    init {
        stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
    }
    ...
}

Java

class MyAdapter extends RecyclerView.Adapter {

    public Adapter() {
        setStateRestorationPolicy(StateRestorationPolicy.PREVENT_WHEN_EMPTY);
    }
    ...
}

2. Status von zustandsorientierten Listenelementen speichern

Speichern Sie den Status komplexer RecyclerView-Listenelemente, z. B. von Elementen, die EditText-Elemente enthalten. Wenn Sie beispielsweise den Status eines EditText speichern möchten, fügen Sie einen Callback ähnlich einem onClick-Handler hinzu, um Textänderungen zu erfassen. Legen Sie innerhalb des Callbacks fest, welche Daten gespeichert werden sollen:

Kotlin

input.addTextChangedListener(
    afterTextChanged = { text ->
        text?.let {
            // Save state here.
        }
    }
)

Java

input.addTextChangedListener(new TextWatcher() {

    ...

    @Override
    public void afterTextChanged(Editable s) {
        // Save state here.
    }
});

Deklariere den Callback in Activity oder Fragment. Verwenden Sie einen ViewModel, um den Status zu speichern.

3. Status des Listenelements zu Adapter hinzufügen

Fügen Sie den Status von Listenelementen zu RecyclerView.Adapter hinzu. Übergeben Sie den Elementstatus an den Adapterkonstruktor, wenn der Host Activity oder Fragment erstellt wird:

Kotlin

val adapter = MyAdapter(items, viewModel.retrieveState())

Java

MyAdapter adapter = new MyAdapter(items, viewModel.retrieveState());

4. Status des Listenelements in ViewHolder des Adapters wiederherstellen

Wenn Sie in der RecyclerView.Adapter eine ViewHolder an ein Element binden, stellen Sie den Status des Elements wieder her:

Kotlin

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    ...
    val item = items[position]
    val state = states.firstOrNull { it.item == item }

    if (state != null) {
        holder.restore(state)
    }
}

Java

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    ...
    Item item = items[position];
    Arrays.stream(states).filter(state -> state.item == item)
        .findFirst()
        .ifPresent(state -> holder.restore(state));
}

Ergebnis

RecyclerView kann jetzt die Scrollposition und den Status aller Elemente in der RecyclerView-Liste wiederherstellen.

Zusätzliche Ressourcen

Verwaltung von abnehmbaren Tastaturen

3-Sterne-Bewertung

Durch die Unterstützung abnehmbarer Tastaturen wird die Nutzerproduktivität auf Geräten mit großen Bildschirmen maximiert. Android löst jedes Mal eine Konfigurationsänderung aus, wenn eine Tastatur an ein Gerät angeschlossen oder von diesem getrennt wird, was zu einem Verlust des UI-Status führen kann. Ihre App kann entweder ihren Status speichern und wiederherstellen, sodass das System die Wiederherstellung von Aktivitäten abwickeln kann, oder die Erholung von Aktivitäten einschränken, wenn Änderungen an der Tastaturkonfiguration vorgenommen werden. In allen Fällen werden alle Daten im Zusammenhang mit der Tastatur in einem Configuration-Objekt gespeichert. Die Felder keyboard und keyboardHidden des Konfigurationsobjekts enthalten Informationen zum Tastaturtyp und zu seiner Verfügbarkeit.

Best Practices

Für große Bildschirme optimierte Apps unterstützen alle Arten von Eingabegeräten, von Software- und Hardwaretastaturen bis hin zu Eingabestiften, Maus, Touchpad und anderen Peripheriegeräten.

Die Unterstützung externer Tastaturen umfasst Konfigurationsänderungen, die Sie auf zwei Arten verwalten können:

  1. Lassen Sie das System die derzeit ausgeführte Aktivität neu erstellen und Sie sind dafür verantwortlich, den Status Ihrer App zu verwalten.
  2. Verwalten Sie die Konfigurationsänderung selbst (die Aktivität wird nicht neu erstellt):
    • Alle tastaturbezogenen Konfigurationswerte deklarieren
    • Handler für Konfigurationsänderung erstellen

Produktivitätsanwendungen, die für die Texteingabe und andere Eingaben häufig eine detaillierte Steuerung der UI erfordern, können von einem Do-it-yourself-Ansatz zur Handhabung von Konfigurationsänderungen profitieren.

In besonderen Fällen kann es sinnvoll sein, das App-Layout zu ändern, wenn eine Hardwaretastatur angebracht oder getrennt ist, z. B. um mehr Platz für Tools oder Bearbeitungsfenster zu schaffen.

Da die einzige zuverlässige Möglichkeit zum Überwachen von Konfigurationsänderungen darin besteht, die Methode onConfigurationChanged() einer Ansicht zu überschreiben, können Sie Ihrer App-Aktivität eine neue View-Instanz hinzufügen und im onConfigurationChanged()-Handler der Ansicht auf Konfigurationsänderungen reagieren, die durch das Anbringen oder Trennen der Tastatur verursacht werden.

Zutaten

  • android:configChanges: Attribut des Elements <activity> des App-Manifests. Informiert das System über Konfigurationsänderungen, die von der App verwaltet werden
  • View#onConfigurationChanged(): Methode, die auf die Weitergabe einer neuen Anwendungskonfiguration reagiert.

Schritte

Zusammenfassung

Deklarieren Sie das Attribut configChanges und fügen Sie tastaturbezogene Werte hinzu. Fügen Sie der Ansichtshierarchie der Aktivität eine View hinzu und achten Sie auf Konfigurationsänderungen.

1. Attribut configChanges deklarieren

Aktualisieren Sie das <activity>-Element im App-Manifest, indem Sie die keyboard|keyboardHidden-Werte der Liste der bereits verwalteten Konfigurationsänderungen hinzufügen:

<activity
      …
      android:configChanges="...|keyboard|keyboardHidden">

2. Leere Ansicht zur Ansichtshierarchie hinzufügen

Geben Sie eine neue Ansicht an und fügen Sie den Handler-Code in der Methode onConfigurationChanged() der Ansicht hinzu:

Kotlin

val v = object : View(this) {
  override fun onConfigurationChanged(newConfig: Configuration?) {
    super.onConfigurationChanged(newConfig)
    // Handler code here.
  }
}

Java

View v = new View(this) {
    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Handler code here.
    }
};

Ergebnis

Deine App reagiert jetzt, wenn eine externe Tastatur angeschlossen oder getrennt wird, ohne die derzeit laufende Aktivität neu zu erstellen.

Zusätzliche Ressourcen

Informationen zum Speichern des UI-Status der App bei Konfigurationsänderungen wie z. B. beim Befestigen oder Trennen der Tastatur finden Sie unter UI-Status speichern.