Große aufgeklappte Displays und einzigartiges zugeklapptes Display ermöglichen auf faltbaren Geräten neue Möglichkeiten für Nutzer. Verwenden Sie die Jetpack WindowManager-Bibliothek, um Ihre App mit Auffaltung zu erkennen. Sie bietet eine API-Oberfläche für Fensterfunktionen faltbarer Geräte, z. B. auf- und zuklappen. Wenn bei Ihrer App „Falten“ berücksichtigt wird, kann das Layout angepasst werden, damit wichtige Inhalte nicht im Bereich von Falten oder Scharnieren platziert werden. Falten und Scharniere dienen außerdem als natürliche Trennelemente.
Fensterinformationen
Die WindowInfoTracker
-Oberfläche in Jetpack WindowManager zeigt Fensterlayoutinformationen an. Die Methode windowLayoutInfo()
der Oberfläche gibt einen Stream von WindowLayoutInfo
-Daten zurück, die Ihre App darüber informieren, dass ein faltbares Gerät zusammengeklappt ist. Mit der Methode WindowInfoTracker
getOrCreate()
wird eine Instanz von WindowInfoTracker
erstellt.
WindowManager unterstützt das Erfassen von WindowLayoutInfo
-Daten mithilfe von Kotlin-Abläufen und Java-Callbacks.
Kotlin-Datenflüsse
Zum Starten und Beenden der WindowLayoutInfo
-Datenerfassung können Sie eine neustartfähige, lebenszyklusbezogene Koroutine verwenden. Dabei wird der Codeblock repeatOnLifecycle
ausgeführt, wenn der Lebenszyklus mindestens STARTED
beträgt, und beendet wird, wenn der Lebenszyklus STOPPED
ist. Die Ausführung des Codeblocks wird automatisch neu gestartet, wenn der Lebenszyklus wieder STARTED
ist. Im folgenden Beispiel werden durch den Codeblock WindowLayoutInfo
-Daten erhoben und verwendet:
class DisplayFeaturesActivity : AppCompatActivity() {
private lateinit var binding: ActivityDisplayFeaturesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDisplayFeaturesBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycleScope.launch(Dispatchers.Main) {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
WindowInfoTracker.getOrCreate(this@DisplayFeaturesActivity)
.windowLayoutInfo(this@DisplayFeaturesActivity)
.collect { newLayoutInfo ->
// Use newLayoutInfo to update the layout.
}
}
}
}
}
Java-Callbacks
Mit der Callback-Kompatibilitätsschicht, die in der androidx.window:window-java
-Abhängigkeit enthalten ist, können Sie WindowLayoutInfo
-Updates erfassen, ohne einen Kotlin-Ablauf zu verwenden. Das Artefakt enthält die Klasse WindowInfoTrackerCallbackAdapter
, die eine WindowInfoTracker
anpasst, um das Registrieren (und Aufheben der Registrierung) von Callbacks zu unterstützen und WindowLayoutInfo
-Updates zu erhalten, zum Beispiel:
public class SplitLayoutActivity extends AppCompatActivity {
private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private ActivitySplitLayoutBinding binding;
private final LayoutStateChangeCallback layoutStateChangeCallback =
new LayoutStateChangeCallback();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
windowInfoTracker =
new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}
@Override
protected void onStart() {
super.onStart();
windowInfoTracker.addWindowLayoutInfoListener(
this, Runnable::run, layoutStateChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
windowInfoTracker
.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}
class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
SplitLayoutActivity.this.runOnUiThread( () -> {
// Use newLayoutInfo to update the layout.
});
}
}
}
RxJava-Unterstützung
Wenn Sie bereits RxJava
(Version 2
oder 3
) verwenden, können Sie Artefakte nutzen, die es Ihnen ermöglichen, mit Observable
oder Flowable
Updates zu erfassen, ohne einen Kotlin-Ablauf zu verwenden.WindowLayoutInfo
Die von den Abhängigkeiten androidx.window:window-rxjava2
und androidx.window:window-rxjava3
bereitgestellte Kompatibilitätsebene enthält die Methoden WindowInfoTracker#windowLayoutInfoFlowable()
und WindowInfoTracker#windowLayoutInfoObservable()
, mit denen Ihre App WindowLayoutInfo
-Updates erhalten kann. Beispiel:
class RxActivity: AppCompatActivity {
private lateinit var binding: ActivityRxBinding
private var disposable: Disposable? = null
private lateinit var observable: Observable<WindowLayoutInfo>
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Create a new observable
observable = WindowInfoTracker.getOrCreate(this@RxActivity)
.windowLayoutInfoObservable(this@RxActivity)
}
@Override
protected void onStart() {
super.onStart();
// Subscribe to receive WindowLayoutInfo updates
disposable?.dispose()
disposable = observable
.observeOn(AndroidSchedulers.mainThread())
.subscribe { newLayoutInfo ->
// Use newLayoutInfo to update the layout
}
}
@Override
protected void onStop() {
super.onStop();
// Dispose the WindowLayoutInfo observable
disposable?.dispose()
}
}
Funktionen faltbarer Displays
Mit der Klasse WindowLayoutInfo
von Jetpack WindowManager werden die Funktionen eines Anzeigefensters als Liste von DisplayFeature
-Elementen verfügbar gemacht.
Ein FoldingFeature
ist eine Art von DisplayFeature
, das unter anderem die folgenden Informationen zu faltbaren Displays bietet:
state
: der zusammengeklappte Zustand des Geräts,FLAT
oderHALF_OPENED
orientation
: Ausrichtung der Faltung oder des ScharniersHORIZONTAL
oderVERTICAL
occlusionType
: Gibt an, ob der Umklapp oder das Scharnier einen Teil des Displays verdeckt,NONE
oderFULL
isSeparating
: Gibt an, ob durch die Faltung oder das Scharnier zwei logische Anzeigebereiche erstellt werden (wahr oder falsch)
Bei faltbaren Geräten mit HALF_OPENED
wird „isSeparating
“ immer als „true“ eingestuft, weil der Bildschirm in zwei Bereiche unterteilt ist. Außerdem ist „isSeparating
“ auf einem Gerät mit Dual Screen immer „true“, wenn die App beide Bildschirme umfasst.
Die Eigenschaft FoldingFeature
bounds
(übernommen von DisplayFeature
) steht für das Begrenzungsrechteck eines Faltelements, z. B. eines Faltelements oder Scharniers. Die Grenzen können verwendet werden, um Elemente auf dem Bildschirm relativ zum Element zu positionieren.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { // Safely collects from windowInfoRepo when the lifecycle is STARTED // and stops collection when the lifecycle is STOPPED WindowInfoTracker.getOrCreate(this@MainActivity) .windowLayoutInfo(this@MainActivity) .collect { layoutInfo -> // New posture information val foldingFeature = layoutInfo.displayFeatures .filterIsInstance() .firstOrNull() // Use information from the foldingFeature object } } } }
Java
private WindowInfoTrackerCallbackAdapter windowInfoTracker; private final LayoutStateChangeCallback layoutStateChangeCallback = new LayoutStateChangeCallback(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { ... windowInfoTracker = new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this)); } @Override protected void onStart() { super.onStart(); windowInfoTracker.addWindowLayoutInfoListener( this, Runnable::run, layoutStateChangeCallback); } @Override protected void onStop() { super.onStop(); windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback); } class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> { @Override public void accept(WindowLayoutInfo newLayoutInfo) { // Use newLayoutInfo to update the Layout List<DisplayFeature> displayFeatures = newLayoutInfo.getDisplayFeatures(); for (DisplayFeature feature : displayFeatures) { if (feature instanceof FoldingFeature) { // Use information from the feature object } } } }
Modus „Auf dem Tisch“
Mithilfe der Informationen aus dem FoldingFeature
-Objekt kann deine App Sicherheitsstatus wie den Modus „Auf dem Tisch“ unterstützen,
Das Smartphone liegt auf einer Oberfläche, das Scharnier ist horizontal positioniert und das faltbare Display ist zur Hälfte geöffnet.
Mit dem Modus „Auf dem Tisch“ können Nutzer ihr Smartphone ohne das Smartphone in den Händen halten. Der Modus „Auf dem Tisch“ eignet sich hervorragend zum Ansehen von Medien, zum Aufnehmen von Fotos und für Videoanrufe.
FoldingFeature.State
verwenden
und FoldingFeature.Orientation
So finden Sie heraus, ob sich das Gerät im Modus „Auf dem Tisch“ befindet:
Kotlin
fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL }
Java
boolean isTableTopPosture(FoldingFeature foldFeature) { return (foldFeature != null) && (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) && (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL); }
Sobald du weißt, dass sich das Gerät im Modus „Auf dem Tisch“ befindet, aktualisiere das App-Layout entsprechend. Bei Medien-Apps bedeutet das in der Regel, die Wiedergabe „above the fold“ zu platzieren und die Positionierung von Steuerelementen und ergänzende Inhalte direkt unten.
Beispiele
MediaPlayerActivity
App: Informationen zur Verwendung von Media3 Exoplayer und WindowManager, um einen faltbaren Videoplayer zu erstellen.Codelab Kamera aufklappen: Hier erfährst du, wie du den Modus „Auf dem Tisch“ in Foto-Apps implementierst. Blenden Sie den Sucher in der oberen Hälfte des Bildschirms „above the fold“ (ohne Scrollen sichtbar) und die Steuerelemente in der unteren Hälfte „below the fold“ ein.
Buchmodus
Eine weitere einzigartige faltbare Haltung ist der Buchmodus, in dem das Gerät zur Hälfte geöffnet ist. und das Scharnier ist vertikal. Der Buchmodus eignet sich hervorragend zum Lesen von E-Books. Bei einer zweiseitigen Layout auf einem großen Bildschirm faltbar, aufgeklappt wie bei einem Buch, im Buchmodus ein echtes Buch zu lesen.
Sie kann auch für Fotos verwendet werden, wenn Sie ein anderes Seitenverhältnis aufnehmen möchten, während Sie per Sprachbefehl Fotos aufnehmen.
Implementieren Sie den Buchmodus mit denselben Techniken, die auch für den Modus „Auf dem Tisch“ verwendet werden. Der einzige Unterschied ist die Code sollte überprüfen, ob die Ausrichtung des Faltelements vertikal statt horizontal ist:
Kotlin
fun isBookPosture(foldFeature : FoldingFeature?) : Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.VERTICAL }
Java
boolean isBookPosture(FoldingFeature foldFeature) { return (foldFeature != null) && (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) && (foldFeature.getOrientation() == FoldingFeature.Orientation.VERTICAL); }
Änderungen der Fenstergröße
Der Anzeigebereich einer App kann sich infolge einer Änderung der Gerätekonfiguration ändern, z. B. wenn das Gerät auf- oder zugeklappt oder gedreht wird oder wenn die Größe eines Fensters im Mehrfenstermodus angepasst wird.
Mit der Jetpack-WindowManager-Klasse WindowMetricsCalculator
können Sie die aktuellen und maximalen Fenstermesswerte abrufen. Wie bei der in API-Level 30 eingeführten Plattform WindowMetrics
gibt der WindowManager WindowMetrics
die Fenstergrenzen an, aber die API ist bis API-Level 14 abwärtskompatibel.
Siehe Fenstergrößenklassen.
Weitere Informationen
Produktproben
- Jetpack WindowManager: Beispiel für die Verwendung der Jetpack WindowManager-Bibliothek
- Jetcaster: Implementierung des Tabellenstatus mit Compose
Codelabs
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Mit Jetpack WindowManager unterstützen Sie faltbare und Dual-Screen-Geräte.
- Kamera-App auf faltbaren Geräten mit Jetpack WindowManager optimieren
- Gerätekompatibilitätsmodus