Sie benötigen verschiedene Arten von Informationen, z. B. zur Gerätefunktion und zum App-Status, um das App-Layout zu aktualisieren. Die Fensterbreite und ‑höhe sind die am häufigsten verwendeten Informationen. Darüber hinaus können Sie sich die folgenden Informationen ansehen:
- Fensterposition
- Präzision von Zeigegeräten
- Tastaturtyp
- Gibt an, ob Kamera und Mikrofon vom Gerät unterstützt werden.
- Der Abstand zwischen einem Nutzer und dem Gerätedisplay
Da die Informationen dynamisch aktualisiert werden, müssen Sie sie im Blick behalten und die Neuzusammenstellung auslösen, wenn eine Aktualisierung erfolgt.
Die Funktion mediaQuery abstrahiert die Details des Abrufs von Informationen und ermöglicht es Ihnen, sich auf die Definition der Bedingung zu konzentrieren, die die Layoutaktualisierungen auslöst.
Im folgenden Beispiel wird das Layout auf TabletopLayout umgestellt, wenn sich das faltbare Gerät im Tischmodus befindet:
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Funktion mediaQuery aktivieren
Wenn Sie die Funktion mediaQuery aktivieren möchten, legen Sie das Attribut isMediaQueryIntegrationEnabled des ComposeUiFlags-Objekts auf true fest:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
Bedingung mit Parametern definieren
Sie können eine Bedingung als Lambda definieren, das in UiMediaScope ausgewertet wird.
Die mediaQuery-Funktion wertet die Bedingung anhand des aktuellen Status und der Gerätefunktionen aus.
Die Funktion gibt einen booleschen Wert zurück. Sie können das Layout also mit bedingten Verzweigungen wie einem if-Ausdruck bestimmen.
In Tabelle 1 werden die in UiMediaScope verfügbaren Parameter beschrieben.
| Parameter | Werttyp | Beschreibung |
|---|---|---|
windowWidth |
Dp |
Die aktuelle Fensterbreite in dp. |
windowHeight |
Dp |
Die aktuelle Fensterhöhe in dp. |
windowPosture |
UiMediaScope.Posture |
Die aktuelle Ausrichtung des Anwendungsfensters. |
pointerPrecision |
UiMediaScope.PointerPrecision |
Die höchste Präzision der verfügbaren Zeigegeräte. |
keyboardKind |
UiMediaScope.KeyboardKind |
Der Typ der verfügbaren oder verbundenen Tastatur. |
hasCamera |
Boolean |
Gibt an, ob die Kamera auf dem Gerät unterstützt wird. |
hasMicrophone |
Boolean |
Gibt an, ob das Mikrofon auf dem Gerät unterstützt wird. |
viewingDistance |
UiMediaScope.ViewingDistance |
Der typische Abstand zwischen dem Nutzer und dem Gerätebildschirm. |
Ein UiMediaScope-Objekt löst die Werte der Parameter auf.
Die Funktion mediaQuery verwendet LocalUiMediaScope.current, um auf das UiMediaScope-Objekt zuzugreifen, das die aktuellen Gerätefunktionen und den Kontext darstellt.
Dieses Objekt wird dynamisch aktualisiert, wenn Änderungen vorgenommen werden, z. B. wenn der Nutzer die Geräteausrichtung ändert.
Die mediaQuery-Funktion wertet dann das query-Lambda mit dem aktualisierten UiMediaScope-Objekt aus und gibt einen booleschen Wert zurück.
Im folgenden Beispiel wird basierend auf dem Parameterwert windowPosture zwischen TabletopLayout und FlatLayout ausgewählt.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Entscheidung basierend auf der Fenstergröße treffen
Fenstergrößenklassen sind eine Reihe von Viewport-Breakpoints, die Ihnen beim Entwerfen, Entwickeln und Testen adaptiver Layouts helfen.
Sie können die beiden Parameter, die die aktuelle Fenstergröße darstellen, mit dem in den Fenstergrößenklassen definierten Schwellenwert vergleichen.
Im folgenden Beispiel wird die Anzahl der Bereiche entsprechend der Fensterbreite geändert.
Die Klasse WindowSizeClass enthält Konstanten für die Grenzwerte der Fenstergrößenklassen (Abbildung 1).
Die Funktion derivedMediaQuery wertet das Lambda query aus und umschließt das Ergebnis mit einem derivedStateOf.
Da windowWidth und windowHeight häufig aktualisiert werden können, sollten Sie die Funktion derivedMediaQuery anstelle der Funktion mediaQuery aufrufen, wenn Sie in der query-Lambda auf diese Parameter verweisen.
val narrowerThanMedium by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp } val narrowerThanExpanded by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp } when { narrowerThanMedium -> SinglePaneLayout() narrowerThanExpanded -> TwoPaneLayout() else -> ThreePaneLayout() }
Layout entsprechend der Fensterposition anpassen
Der Parameter windowPosture beschreibt die aktuelle Fensterposition als UiMediaScope.Posture-Objekt.
Sie können die aktuelle posture prüfen, indem Sie den Parameter mit den in der Klasse UiMediaScope.Posture definierten Werten vergleichen.
Im folgenden Beispiel wird das Layout entsprechend der Fensterposition gewechselt:
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
Präzision des verfügbaren Zeigegeräts prüfen
Ein hochpräzises Zeigegerät hilft Nutzern, ein UI-Element genau zu positionieren. Die Genauigkeit eines Zeigegeräts hängt vom Gerätetyp ab.
Der Parameter pointerPrecision beschreibt die Präzision der verfügbaren Zeigegeräte wie Maus und Touchscreen.
In der Klasse UiMediaScope.PointerPrecision sind vier Werte definiert: Fine, Coarse, Blunt und None.
None bedeutet, dass kein Zeigegerät verfügbar ist.
Die Genauigkeit reicht von höchster bis niedrigster in dieser Reihenfolge: Fine, Coarse und Blunt.
Wenn mehrere Zeigegeräte verfügbar sind und ihre Genauigkeiten unterschiedlich sind, wird der Parameter mit der höchsten Genauigkeit aufgelöst.
Wenn es beispielsweise zwei Zeigegeräte gibt – ein Gerät mit Fine-Präzision und ein Gerät mit Blunt-Präzision –, ist Fine der Wert des Parameters pointerPrecision.
Das folgende Beispiel zeigt eine größere Schaltfläche, wenn der Nutzer ein ungenaues Zeigegerät verwendet:
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
Verfügbaren Tastaturtyp prüfen
Der Parameter keyboardKind steht für den Typ der verfügbaren Tastaturen: Physical, Virtual und None.
Wenn eine Bildschirmtastatur angezeigt wird und gleichzeitig eine Hardwaretastatur verfügbar ist, wird der Parameter als Physical aufgelöst.
Wenn keines der beiden erkannt wird, ist None der Wert des Parameters.
Das folgende Beispiel zeigt eine Meldung, in der Nutzer aufgefordert werden, eine Tastatur anzuschließen, wenn keine Tastatur erkannt wird:
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
Prüfen, ob das Gerät Kamera und Mikrofon unterstützt
Einige Geräte unterstützen keine Kameras oder Mikrofone.
Mit dem Parameter hasCamera und dem Parameter hasMicrophone können Sie prüfen, ob das Gerät eine Kamera und ein Mikrofon unterstützt.
Das folgende Beispiel zeigt Schaltflächen für die Verwendung mit Kamera und Mikrofon, wenn das Gerät diese unterstützt:
Row { OutlinedTextField(state = rememberTextFieldState()) // Show the MicButton when the device supports a microphone. if (mediaQuery { hasMicrophone }) { MicButton() } // Show the CameraButton when the device supports a camera. if (mediaQuery { hasCamera }) { CameraButton() } }
Benutzeroberfläche an den geschätzten Betrachtungsabstand anpassen
Der Betrachtungsabstand ist ein Faktor, der bei der Bestimmung des Layouts hilft.
Wenn der Nutzer die App aus der Ferne verwendet, erwartet er, dass Text und UI-Elemente größer sind.
Der Parameter viewingDistance liefert eine Schätzung des Betrachtungsabstands basierend auf dem Gerätetyp und dem typischen Nutzungskontext.
In der Klasse UiMediaScope.ViewingDistance sind drei Werte definiert: Near, Medium und Far.
Near bedeutet, dass sich das Display in unmittelbarer Nähe befindet, und Far, dass das Gerät aus der Ferne betrachtet wird.
Im folgenden Beispiel wird die Schriftgröße erhöht, wenn der Betrachtungsabstand Far oder Medium beträgt:
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
Vorschau einer UI-Komponente ansehen
Sie können die Funktionen mediaQuery und derivedMediaQuery in den zusammensetzbaren Funktionen aufrufen, um eine Vorschau von UI-Komponenten zu sehen.
Im folgenden Snippet wird je nach Wert des Parameters windowPosture zwischen TabletopLayout und FlatLayout ausgewählt.
Wenn Sie eine Vorschau von TabletopLayout anzeigen möchten, sollte der Parameter windowPosture auf UiMediaScope.Posture.Tabletop festgelegt werden.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
Die Funktionen mediaQuery und derivedMediaQuery werten das angegebene query-Lambda in einem UiMediaScope-Objekt aus, das als LocalUiMediaScope.current bereitgestellt wird.
So können Sie die Einstellung überschreiben:
- Aktivieren Sie die Funktion
mediaQuery. - Definieren Sie ein benutzerdefiniertes Objekt, das die
UiMediaScope-Schnittstelle implementiert. - Legen Sie das benutzerdefinierte Objekt mit der Funktion
CompositionLocalProvideraufLocalUiMediaScopefest. - Rufen Sie das Composable auf, das in der Vorschau im Content-Lambda der Funktion
CompositionLocalProviderangezeigt werden soll.
Mit dem folgenden Beispiel können Sie sich eine Vorschau von TabletopLayout ansehen:
@Preview @Composable fun PreviewLayoutForTabletop() { // Step 1: Enable the mediaQuery function ComposeUiFlags.isMediaQueryIntegrationEnabled = true val currentUiMediaScope = LocalUiMediaScope.current // Step 2: Define a custom object implementing the UiMediaScope interface. // The object overrides the windowPosture parameter. // The resolution of the remaining parameters is deferred to the currentUiMediaScope object. val uiMediaScope = remember(currentUiMediaScope) { object : UiMediaScope by currentUiMediaScope { override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop } } // Step 3: Set the object to the LocalUiMediaScope. CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) { // Step 4: Call the composable to preview. when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() } } }