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:
- 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 in modo dinamico,
devi monitorarle e attivare la ricomposizione quando si verifica un aggiornamento.
La funzione mediaQuery astrae i dettagli del recupero di informazioni e ti consente di concentrarti sulla definizione della condizione per attivare gli aggiornamenti del layout.
L'esempio seguente cambia il layout in TabletopLayout
quando la posizione del pieghevole è in modalità tavolo:
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Attiva 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() } }
Definisci una condizione con parametri
Puoi definire una condizione come lambda che viene 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 della finestra corrente 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 fotocamera è supportata sul dispositivo. |
hasMicrophone |
Boolean |
Indica 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 posizione del dispositivo.
La funzione mediaQuery valuta quindi la funzione 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 parametro windowPosture.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
Prendi una decisione in base alle dimensioni della finestra
Le classi di dimensioni delle finestre sono un insieme di breakpoint dei viewport predefiniti che ti aiutano a progettare, sviluppare e testare layout adattivi.
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 contiene costanti per le soglie delle classi di dimensioni della finestra (Figura 1).
La funzione derivedMediaQuery valuta la funzione lambda query e aggrega 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 funzione 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 posizione della finestra
Il parametro windowPosture descrive la postura corrente della finestra come oggetto UiMediaScope.Posture.
Puoi controllare la postura corrente 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() }
Controlla la precisione del dispositivo di puntamento disponibile
Un dispositivo di puntamento ad alta precisione aiuta gli utenti a puntare con precisione un elemento UI. 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 indica che non è disponibile alcun dispositivo di puntamento.
La precisione varia dalla più alta alla più bassa 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 quella più alta.
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 con 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 ed è disponibile contemporaneamente una tastiera hardware, il parametro viene risolto come Physical.
Se non viene rilevato nessuno dei due, il valore del parametro è None.
L'esempio seguente mostra un messaggio che suggerisce agli utenti di collegare una tastiera quando non ne viene rilevata nessuna:
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
Controlla se il dispositivo supporta la fotocamera 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.
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() } }
Regola la UI in base alla distanza di visione stimata
La distanza di visione è un fattore che aiuta a determinare il layout.
Se l'utente utilizza l'app da lontano,
si aspetta che il testo e gli elementi UI siano più grandi.
Il parametro viewingDistance fornisce una stima della distanza di visione 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 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 }
Visualizza l'anteprima di un componente UI
Puoi chiamare le funzioni mediaQuery e derivedMediaQuery nelle funzioni componibili per visualizzare l'anteprima dei componenti della UI.
Lo snippet seguente 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 funzione lambda query specificata all'interno di un oggetto UiMediaScope,
fornito come LocalUiMediaScope.current.
Puoi eseguire l'override con i seguenti passaggi:
- Attiva la funzione
mediaQuery. - Definisci un oggetto personalizzato che implementa l'interfaccia
UiMediaScope. - Imposta l'oggetto personalizzato su
LocalUiMediaScopecon la funzioneCompositionLocalProvider. - Chiama il composable per visualizzare l'anteprima nella funzione 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() } } }