Per aggiornare il layout dell'app, hai bisogno di vari tipi di informazioni, come le 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:
- Postura 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 il display 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.
L'esempio seguente passa al layout TabletopLayout
quando la postura del dispositivo pieghevole è su un tavolo:
@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 dell'oggetto
ComposeUiFlags su true:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
Definire una condizione con parametri
Puoi definire una condizione come lambda
che viene valutata in UiMediaScope.
La funzione mediaQuery valuta la condizione in base
allo stato attuale e alle funzionalità del dispositivo.
La funzione restituisce un valore booleano,
in modo da poter 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 della finestra corrente in dp. |
windowPosture |
UiMediaScope.Posture |
La postura attuale della finestra dell'applicazione. |
pointerPrecision |
UiMediaScope.PointerPrecision |
La massima precisione dei dispositivi di puntamento disponibili. |
keyboardKind |
UiMediaScope.KeyboardKind |
Il tipo di tastiera disponibile o collegata. |
hasCamera |
Boolean |
Indica 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 del dispositivo corrente.
Questo oggetto viene aggiornato dinamicamente quando vengono apportate modifiche,
ad esempio quando l'utente cambia la postura del dispositivo.
La funzione mediaQuery valuta quindi la funzione lambda query
con l'oggetto UiMediaScope aggiornato e restituisce un valore booleano.
Ad esempio, il seguente snippet 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 del viewport
che ti aiutano a progettare, sviluppare e testare layout adattabili.
Puoi confrontare i due parametri che rappresentano le dimensioni della finestra corrente
con la soglia definita nelle classi di dimensioni della finestra.
L'esempio seguente modifica il numero di riquadri in base alla larghezza della finestra.
La classe WindowSizeClass ha costanti per le soglie delle classi di dimensioni della finestra (Figura 1).
La funzione derivedMediaQuery 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 nella 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() }
Aggiorna il layout in base alla postura della finestra
Il parametro windowPosture descrive la postura della finestra corrente
come oggetto UiMediaScope.Posture.
Puoi controllare la postura attuale confrontando il parametro
con i valori definiti nella classe UiMediaScope.Posture.
L'esempio seguente cambia il layout in base alla postura 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 mouse e 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 dal massimo al minimo nel seguente 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, un dispositivo di precisione Fine e un dispositivo di precisione Blunt, Fine è il valore del parametro pointerPrecision.
L'esempio seguente mostra un pulsante più grande quando l'utente utilizza un dispositivo di puntamento a bassa precisione:
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
Controlla 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 rilevato nessuno dei due, None è il valore del parametro.
Il seguente esempio 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 i parametri hasCamera e hasMicrophone.
Il seguente esempio 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 in base alla distanza di visualizzazione stimata
La distanza di visualizzazione è un fattore che contribuisce 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 indica che lo schermo è a distanza ravvicinata,
mentre Far indica che il dispositivo viene visualizzato da lontano.
L'esempio seguente aumenta la dimensione 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 UI
Puoi chiamare le funzioni mediaQuery e derivedMediaQuery nelle
funzioni componibili per visualizzare l'anteprima dei componenti UI.
Il seguente snippet sceglie tra TabletopLayout
e FlatLayout in base al valore 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
la lambda query specificata all'interno di un oggetto UiMediaScope,
che viene fornito come LocalUiMediaScope.current.
Puoi ignorarlo procedendo nel seguente modo:
- Attiva la funzione
mediaQuery. - Definisci un oggetto personalizzato che implementa l'interfaccia
UiMediaScope. - Imposta l'oggetto personalizzato su
LocalUiMediaScopecon la funzioneCompositionLocalProvider. - Chiama il componibile per visualizzarlo in anteprima nella lambda dei contenuti della funzione
CompositionLocalProvider.
Puoi visualizzare l'anteprima di TabletopLayout con il seguente esempio:
@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() } } }