Jetpack-Fenster-Manager für faltbare Geräte

Der Jetpack-Fenster-Manager stellt eine Standard-API für die Arbeit mit allen faltbaren Geräten bereit. Sie enthält zwei wichtige Klassen:

  • DisplayFeature: Erkennt Unterbrechungen der fortlaufenden flachen Bildschirmoberfläche wie Scharniere oder Faltungen. Der Fenster-Manager gibt eine Sammlung von Anzeigefeatures aus einem Rückruf für Layoutänderungen zurück.
  • FoldingFeature: Bietet Informationen zu einem bestimmten Feature des Geräts. Surface Duo weist nur ein Faltfeature auf, es ist aber möglich, dass andere Geräte mehr bieten.

Ein ähnlicher Leitfaden befindet sich im Android Foldable Codelab. Weitere Informationen zum Entwickeln für faltbare Geräte finden Sie in der Android-Dokumentation. Beispiele vom Android-Team sind auch auf GitHub verfügbar. In den Jetpack-Versionshinweisen werden Änderungen im Fenster-Manager erfasst, wenn er aktualisiert wird.

Tipp

Die Steuerelemente und Hilfsklassen in der Surface Duo-Doppelbildschirm-Bibliothek funktionieren mit dem Fenster-Manager. Folgen Sie den Anweisungen, um Ihrem App-Projekt die richtigen Pakete hinzuzufügen.

Befolgen Sie die Anweisungen unten, um den Fenster-Manager direkt in Ihrem Code zu verwenden:

Hinzufügen von Abhängigkeiten

  1. Achten Sie darauf, das mavenCentral() -Repository in Ihre build.gradle-Datei der obersten Ebene aufzunehmen:

    allprojects {
        repositories {
            google()
            mavenCentral()
         }
    }
    
  2. Vergewissern Sie sich, dass die compileSdkVersion und targetSdkVersion in Ihrer build.gradle-Datei auf Modulebene auf API 31 oder neuer festgelegt sind:

    android { 
        compileSdkVersion 31
    
        defaultConfig { 
            targetSdkVersion 31
        } 
        ... 
    }
    
    
  3. Fügen Sie Ihrer build.gradle-Datei auf Modulebene die folgenden Abhängigkeiten hinzu:

    dependencies {
        implementation "androidx.window:window:1.0.0"
        implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
    }
    

Verwenden des Fenster-Managers in Ihrem Kotlin-Code

Beim Zugriff auf die Fenster-Manager-Eigenschaften in Ihren Kotlin-Projekten ist es wichtig, den richtigen Informationsfluss einzurichten. Andernfalls empfangen Sie möglicherweise zu wenige oder zu viele Ereignisupdates, und die App-Leistung könnte beeinträchtigt sein.

Führen Sie die Schritte unten aus, um ein WindowInfoTracker-Objekt zu initialisieren und zu verwenden:

  1. Erstellen Sie in Ihrer MainActivity-Klasse eine Variable für den WindowInfoTracker. Achten Sie darauf, dass oben in der Datei import androidx.window.layout.WindowInfoTracker hinzugefügt wird.

    class MainActivity : AppCompatActivity() {
        private lateinit var windowInfoTracker: WindowInfoTracker
    
  2. Initialisieren Sie den WindowInfoTracker in der onCreate-Methode Ihrer Aktivität, und richten Sie einen Flow ein, um Informationen aus der windowLayoutInfo-Eigenschaft zu erfassen.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // Initialize the window manager
        windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity)
    
        // Set up a flow
        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                windowInfoTracker.windowLayoutInfo(this@MainActivity)
                    .collect { 
                        // Check FoldingFeature properties here
                    }
            }
        }
    }
    

    Achten Sie darauf, dass diese Importe ebenfalls am Anfang der Datei hinzugefügt werden:

    import androidx.lifecycle.Lifecycle
    import androidx.lifecycle.lifecycleScope
    import androidx.lifecycle.repeatOnLifecycle
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.flow.collect
    import kotlinx.coroutines.launch
    
  3. Fügen Sie Code hinzu, um den WindowLayoutInfo-Flow auf Eigenschaften des Faltfeatures zu prüfen. Beim Ausführen dieses Codes wird die Aktivität mit der aktuellen Geräteposition und den Anzeigefeatures aktualisiert (im Fall einer ein Scharnier oder eine Faltung überspannenden Darstellung).

    Im nachstehenden Codeausschnitt zeigt die Aktivität unterschiedlichen Text basierend auf den Eigenschaften eines FoldingFeature an.

    Dieses Beispiel enthält eine TextView mit dem Namen layout_change_text, die den Okklusionstyp und den isSeparating-Wert für alle erkannten Faltfeatures angibt.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity)
    
        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                windowInfoTracker.windowLayoutInfo(this@MainActivity)
                    .collect { newLayoutInfo ->
                        layout_change_text.text = "No display features detected"
                        for (displayFeature : DisplayFeature in newLayoutInfo.displayFeatures) {
                            if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.NONE) {
                                layout_change_text.text = "App is spanned across a fold, " +
                                    "isSeparating = ${displayFeature.isSeparating}"
                            }
                            if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.FULL) {
                                layout_change_text.text = "App is spanned across a hinge, " +
                                    "isSeparating = ${displayFeature.isSeparating}"
                            }
                        }
                    }
            }
        }
    }
    

Faltfeature-Eigenschaften

Die Klasse WindowLayoutInfo enthält eine Sammlung von DisplayFeature-Elementen, von denen eins oder mehrere möglicherweise Instanzen der FoldingFeature-Klasse sind.

Faltfeatures weisen die folgenden Eigenschaften auf:

  • bounds: Koordinaten des Begrenzungsrechtecks eines Faltfeatures
  • occlusionType: wenn ein Faltfeature Inhalte ausblendet (FULL oder NONE)
  • orientation: Ausrichtung eines Faltfeatures (HORIZONTAL oder VERTICAL)
  • state: Winkel eines Faltfeatures (HALF_OPENED oder FLAT)
  • isSeparating: wenn ein Faltfeature den Anzeigebereich in zwei verschiedene Abschnitte trennt

Sie können diese Eigenschaften abfragen, um Entscheidungen darüber zu treffen, wie Sie Ihr Layout nach Konfigurationsänderungen anpassen.

isSeparating

Sie verwenden die IsSeparating-Eigenschaft, um zu entscheiden, wo Steuerelemente angezeigt oder wie viele Inhaltsbereiche verwendet werden sollen. Dieses Feld stellt sicher, dass Ihre App auf allen faltbaren Geräten die optimale Benutzererfahrung bietet:

  • Bei Geräten mit Doppelbildschirm ist sie immer TRUE, wenn eine App das Scharnier übergreifend dargestellt wird
  • Bei anderen faltbaren Geräten ist sie nur dann TRUE, wenn der Status HALF_OPENED ist, etwa wenn sich ein Gerät in der Tabletop-Position befindet

Verwenden Sie die isSeparating-Eigenschaft, um festzulegen, ob bei einer Darstellung ohne Trennung das Layout der Benutzeroberfläche für ein faltbares Gerät angepasst oder das Standardlayout verwendet werden soll:

private fun updateCurrentLayout(newLayoutInfo: WindowLayoutInfo) {
   for (displayFeature in newLayoutInfo.displayFeatures) {
       val foldFeature = displayFeature as? FoldingFeature
       foldFeature?.let {
           if (it.isSeparating) {
               // The content is separated by the FoldingFeature.
               // Here is where you should adapt your UI.
           } else {
               // The content is not separated.
               // Users can see and interact with your UI properly.
           }
       }
   }
}

Ein ausführlicheres Beispiel zur Verwendung dieses Felds findet sich in diesem isSeparating-Beispiel.

Google bietet ebenfalls Dokumentationen und Beispiele im Zusammenhang mit dieser Eigenschaft im Rahmen seiner Anleitungen für große Bildschirme und faltbare Geräte.

Beispiele

Das Repository surface-duo-jetpack-window-manager-samples auf GitHub enthält eine Reihe von Kotlin-Beispielen, die verschiedene Muster für die Dual-Screen-Benutzererfahrung veranschaulichen, die mit dem Jetpack-Fenster-Manager und dem herkömmlichen Darstellungssystem erstellt wurden.

Das GitHub-Repository surface-duo-compose-samples enthält außerdem Kotlin-Beispiele für Doppelbildschirmgeräte, die den Jetpack-Fenster-Manager verwenden, doch wird in diesen Beispielen die Benutzeroberfläche mit Jetpack Compose erstellt.

Java-API

Lesen Sie den Blogbeitrag Jetpack Window Manager with Java (Jetpack-Fenster-Manager mit Java) und dieses Java-Beispiel, um zu erfahren, wie Sie über WindowInfoTrackerCallbackAdapter auf die WindowInfoTracker-Klasse zugreifen.

Ressourcen