Sie benötigen verschiedene Arten von Informationen, z. B. zu Gerätefunktionen und zum App-Status, um das App-Layout zu aktualisieren. Die Breite und Höhe des Fensters sind die am häufigsten verwendeten Informationen. Außerdem können Sie die folgenden Informationen heranziehen:
- Fensterstatus
- Präzision von Zeigegeräten
- Tastaturtyp
- Gibt an, ob die Kamera und das Mikrofon vom Gerät unterstützt werden.
- Die Entfernung zwischen einem Nutzer und dem Gerätedisplay
Da die Informationen dynamisch aktualisiert werden, müssen Sie sie im Blick behalten und bei jeder Aktualisierung eine Neuzusammensetzung auslösen.
Die Funktion mediaQuery abstrahiert die Details des Informationsabrufs, sodass Sie sich auf die Definition der Bedingung konzentrieren können, die die Layoutaktualisierungen auslöst.
Im folgenden Beispiel wird das Layout zu TabletopLayout geändert, wenn das faltbare Gerät im Tischmodus ist:
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Funktion mediaQuery aktivieren
Wenn Sie die Funktion mediaQuery aktivieren möchten, setzen Sie das Attribut isMediaQueryIntegrationEnabled des ComposeUiFlags-Objekts auf true:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
Bedingung mit Parametern definieren
Sie können eine Bedingung als Lambda definieren, das innerhalb von UiMediaScope ausgewertet wird.
Die Funktion mediaQuery wertet die Bedingung anhand des aktuellen Status und der Gerätefunktionen aus.
Die Funktion gibt einen booleschen Wert zurück, sodass Sie das Layout mit bedingten Verzweigungen wie einem if-Ausdruck bestimmen können.
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 Position 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 Objekt UiMediaScope 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äteposition ändert.
Die Funktion mediaQuery wertet dann den Lambda-Ausdruck query mit dem aktualisierten UiMediaScope-Objekt aus und gibt einen booleschen Wert zurück.
Im folgenden Snippet wird beispielsweise anhand des Parameterwerts 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 vordefinierten Darstellungsbereich-Breakpoints, die Sie beim Entwerfen, Entwickeln und Testen von adaptiven Layouts unterstützen.
Du kannst 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 je nach Fensterbreite geändert.
Die Klasse WindowSizeClass enthält Konstanten für die Grenzwerte der Fenstergrößenklassen (Abbildung 1).
Die Funktion derivedMediaQuery wertet den Lambda-Ausdruck query aus und verpackt das Ergebnis in ein derivedStateOf.
Da windowWidth und windowHeight häufig aktualisiert werden können, rufen Sie die Funktion derivedMediaQuery anstelle der Funktion mediaQuery auf, wenn Sie im Lambda query 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 aktualisieren
Der Parameter windowPosture beschreibt die aktuelle Fensterposition als UiMediaScope.Posture-Objekt.
Du kannst die aktuelle Haltung prüfen, indem du den Parameter mit den in der Klasse UiMediaScope.Posture definierten Werten vergleichst.
Im folgenden Beispiel wird das Layout je nach Fensterposition geändert:
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 anzusteuern. Die Genauigkeit eines Zeigegeräts hängt vom Gerätetyp ab.
Der Parameter pointerPrecision beschreibt die Genauigkeit der verfügbaren Zeigegeräte, z. B. einer Maus und eines Touchscreens.
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 der höchsten bis zur niedrigsten in dieser Reihenfolge: Fine, Coarse und Blunt.
Wenn mehrere Zeigegeräte verfügbar sind und ihre Genauigkeit unterschiedlich ist, wird der Parameter mit dem höchsten Wert aufgelöst.
Wenn es beispielsweise zwei Zeigegeräte gibt, ein Gerät mit der Genauigkeit Fine und ein Gerät mit der Genauigkeit Blunt, ist Fine der Wert des Parameters pointerPrecision.
Im folgenden Beispiel wird eine größere Schaltfläche angezeigt, wenn der Nutzer ein Zeigegerät mit geringer Präzision 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 von beiden erkannt wird, ist None der Wert des Parameters.
Im folgenden Beispiel wird eine Meldung angezeigt, 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, die mit Kamera und Mikrofon verwendet werden können, 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 der Bildschirm in der 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 der UI-Komponenten zu erhalten.
Im folgenden Snippet wird basierend auf dem Parameterwert windowPosture zwischen TabletopLayout und FlatLayout gewählt.
Für die Vorabversion von TabletopLayout muss der Parameter windowPosture auf UiMediaScope.Posture.Tabletop festgelegt sein.
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 den angegebenen query-Lambda-Ausdruck innerhalb eines UiMediaScope-Objekts aus, das als LocalUiMediaScope.current bereitgestellt wird.
Sie können sie mit den folgenden Schritten überschreiben:
- Aktivieren Sie die Funktion
mediaQuery. - Definieren Sie ein benutzerdefiniertes Objekt, das die Schnittstelle
UiMediaScopeimplementiert. - Legen Sie das benutzerdefinierte Objekt mit der Funktion
CompositionLocalProvideraufLocalUiMediaScopefest. - Rufen Sie die Funktion „composable“ auf, um eine Vorschau im Inhalts-Lambda der Funktion
CompositionLocalProviderzu sehen.
Sie können sich die TabletopLayout mit dem folgenden Beispiel 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() } } }