Per aggiornare il layout dell'app, hai bisogno di vari tipi di informazioni, come la funzionalità del dispositivo e lo stato dell'app. La larghezza e l'altezza della finestra sono le informazioni di uso comune. Inoltre, puoi fare riferimento alle seguenti informazioni:
- Posizione della finestra
- Precisione dei dispositivi di puntamento
- Tipo di tastiera
- Se la videocamera e il microfono sono supportati dal dispositivo
- La distanza tra un utente e lo schermo del dispositivo
Poiché le informazioni vengono aggiornate dinamicamente, devi monitorarle e attivare la ricomposizione quando si verifica un aggiornamento.
La funzione mediaQuery astrae i dettagli del recupero delle informazioni
e ti consente di concentrarti sulla definizione della condizione per attivare gli aggiornamenti del layout.
Il seguente esempio passa al layout TabletopLayout quando la posizione pieghevole è orizzontale:
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Attivare la funzione mediaQuery
Per attivare la funzione mediaQuery,
imposta l'attributo isMediaQueryIntegrationEnabled di
l'oggetto ComposeUiFlags su true:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
Definire una condizione con i parametri
Puoi definire una condizione come un'espressione lambda
valutata all'interno di UiMediaScope.
La funzione mediaQuery valuta la condizione in base allo stato attuale e alle funzionalità del dispositivo.
La funzione restituisce un valore booleano, quindi puoi determinare il layout con rami condizionali come un'espressione if.
La Tabella 1 descrive i parametri disponibili in UiMediaScope.
| Parametro | Tipo di valore | Descrizione |
|---|---|---|
windowWidth |
Dp |
La larghezza attuale della finestra in dp. |
windowHeight |
Dp |
L'altezza attuale della finestra in dp. |
windowPosture |
UiMediaScope.Posture |
La posizione attuale della finestra dell'applicazione. |
pointerPrecision |
UiMediaScope.PointerPrecision |
La precisione più elevata dei dispositivi di puntamento disponibili. |
keyboardKind |
UiMediaScope.KeyboardKind |
Il tipo di tastiera disponibile o connessa. |
hasCamera |
Boolean |
Se la videocamera è supportata sul dispositivo. |
hasMicrophone |
Boolean |
Se il microfono è supportato sul dispositivo. |
viewingDistance |
UiMediaScope.ViewingDistance |
La distanza tipica tra l'utente e lo schermo del dispositivo. |
Un oggetto UiMediaScope risolve i valori dei parametri.
La funzione mediaQuery utilizza LocalUiMediaScope.current
per accedere all'oggetto UiMediaScope,
che rappresenta le funzionalità e il contesto attuali del dispositivo.
Questo oggetto viene aggiornato dinamicamente quando vengono apportate modifiche, ad esempio quando l'utente cambia la posizione del dispositivo.
La funzione mediaQuery valuta quindi l'espressione lambda query con l'oggetto UiMediaScope aggiornato e restituisce un valore booleano.
Ad esempio, lo snippet seguente sceglie tra TabletopLayout e FlatLayout in base al valore del parametro windowPosture.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Prendere una decisione in base alle dimensioni della finestra
Le classi di dimensioni della finestra sono un insieme di punti di interruzione della finestra di visualizzazione
che ti aiutano a progettare, sviluppare e testare layout adattivi.
Puoi confrontare i due parametri che rappresentano le dimensioni attuali della finestra con la soglia definita nelle classi di dimensioni della finestra.
L'esempio seguente modifica il numero di riquadri in base alla larghezza della finestra.
WindowSizeClass classe ha costanti per le soglie
delle classi di dimensioni della finestra (Figura 1).
La derivedMediaQuery funzione valuta l'espressione lambda query
e racchiude il risultato in un derivedStateOf.
Poiché windowWidth e windowHeight possono essere aggiornati di frequente, chiama la funzione derivedMediaQuery anziché la funzione mediaQuery quando fai riferimento a questi parametri nell'espressione lambda query.
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() }
Aggiornare il layout in base alla posizione della finestra
Il parametro windowPosture descrive la posizione attuale della finestra come oggetto UiMediaScope.Posture.
Puoi controllare la posizione attuale postura confrontando il parametro
con i valori definiti nella UiMediaScope.Posture classe.
L'esempio seguente cambia il layout in base alla posizione della finestra:
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
Controllare la precisione del dispositivo di puntamento disponibile
Un dispositivo di puntamento ad alta precisione aiuta gli utenti a puntare con precisione un elemento dell'interfaccia utente. La precisione di un dispositivo di puntamento dipende dal tipo di dispositivo.
Il parametro pointerPrecision descrive la precisione dei dispositivi di puntamento disponibili, come un mouse e un touchscreen.
Nella classe UiMediaScope.PointerPrecision sono definiti quattro valori:
Fine, Coarse, Blunt e None.
None significa che non è disponibile alcun dispositivo di puntamento.
La precisione varia da massima a minima in questo ordine: Fine, Coarse e Blunt.
Se sono disponibili più dispositivi di puntamento e le loro precisioni sono diverse, il parametro viene risolto con la precisione più elevata.
Ad esempio, se sono presenti due dispositivi di puntamento, uno con precisione Fine e uno con precisione Blunt, Fine è il valore del parametro pointerPrecision.
L'esempio seguente mostra un pulsante più grande quando l'utente utilizza un dispositivo di puntamento con bassa precisione:
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
Controllare il tipo di tastiera disponibile
Il parametro keyboardKind rappresenta il tipo di tastiere disponibili:
Physical, Virtual e None.
Se viene visualizzata una tastiera sullo schermo e contemporaneamente è disponibile una tastiera hardware, il parametro viene risolto come Physical.
Se non viene rilevata nessuna delle due, None è il valore del parametro.
L'esempio seguente mostra un messaggio che suggerisce agli utenti di collegare una tastiera quando non viene rilevata alcuna tastiera:
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
Controllare se il dispositivo supporta la videocamera e il microfono
Alcuni dispositivi non supportano videocamere o microfoni.
Puoi verificare se il dispositivo supporta una videocamera e un microfono con il parametro hasCamera e il parametro hasMicrophone.
L'esempio seguente mostra i pulsanti da utilizzare con la videocamera e il microfono quando il dispositivo li supporta:
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() } }
Regolare l'interfaccia utente con la distanza di visualizzazione stimata
La distanza di visualizzazione è un fattore che aiuta a determinare il layout.
Se l'utente utilizza l'app da lontano, si aspetta che il testo e gli elementi dell'interfaccia utente siano più grandi.
Il parametro viewingDistance fornisce una stima della distanza di visualizzazione in base al tipo di dispositivo e al suo contesto di utilizzo tipico.
Nella classe UiMediaScope.ViewingDistance sono definiti tre valori:
Near, Medium e Far.
Near significa che lo schermo è a distanza ravvicinata, mentre Far significa che il dispositivo viene visualizzato da lontano.
L'esempio seguente aumenta le dimensioni del carattere quando la distanza di visualizzazione è Far o Medium:
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
Visualizzare l'anteprima di un componente dell'interfaccia utente
Puoi chiamare le funzioni mediaQuery e derivedMediaQuery nelle funzioni componibili per visualizzare l'anteprima dei componenti dell'interfaccia utente.
Lo snippet seguente sceglie tra TabletopLayout e FlatLayout in base al valore del parametro windowPosture.
Per visualizzare l'anteprima di TabletopLayout, il parametro windowPosture deve essere
UiMediaScope.Posture.Tabletop.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
Le funzioni mediaQuery e derivedMediaQuery valutano
l'espressione lambda query specificata all'interno di un oggetto UiMediaScope,
fornito come LocalUiMediaScope.current.
Puoi sostituirlo seguendo questi passaggi:
- Attiva la funzione
mediaQuery. - Definisci un oggetto personalizzato che implementa l'interfaccia
UiMediaScope. - Imposta l'oggetto personalizzato su
LocalUiMediaScopecon laCompositionLocalProviderfunzione. - Chiama il componibile per visualizzare l'anteprima nell'espressione lambda del contenuto della funzione
CompositionLocalProvider.
Puoi visualizzare l'anteprima di TabletopLayout con l'esempio seguente:
@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() } } }