La piattaforma Android è responsabile del disegno dell'interfaccia utente di sistema, ad esempio la barra di stato e la barra di navigazione. Questa UI di sistema viene visualizzata indipendentemente dal l'app usata dall'utente.
WindowInsets
fornisce informazioni sul sistema
UI per assicurarti che l'app disegna l'area corretta e che l'UI non sia oscurata
dalla UI di sistema.
Su Android 14 (livello API 34) e versioni precedenti, l'UI dell'app non mostra elementi sottostanti. le barre di sistema e i ritagli del display per impostazione predefinita.
Su Android 15 (livello API 35) e versioni successive, la tua app utilizza il sistema. barre e ritagli display quando l'app ha come target l'SDK 35. Ciò si traduce in un un'esperienza utente fluida e consente alla tua app di sfruttare appieno lo spazio a disposizione.
La visualizzazione dei contenuti dietro l'interfaccia utente di sistema è chiamata edge-to-edge. In questo di Google Cloud, scoprirai i diversi tipi di riquadri, come passare da edge-to-edge, e come utilizzare le API integrate per animare la UI e garantire che i contenuti dell'app non sia oscurata da elementi dell'interfaccia utente di sistema.
Concetti fondamentali integrati
Quando un'app va a livello perimetrale, devi assicurarti che i contenuti e le interazioni non sono oscurate dall'interfaccia utente di sistema. Ad esempio, se un pulsante è collocato dietro la barra di navigazione, l'utente potrebbe non essere in grado di fare clic su di esso.
Vengono specificate le dimensioni dell'interfaccia utente di sistema e le informazioni su dove è posizionata tramite insiemi.
Ogni parte dell'interfaccia utente di sistema ha un tipo di insenatura corrispondente che descrive le sue dimensioni e la sua posizione. Ad esempio, i riquadri della barra di stato forniscono le dimensioni e la posizione della barra di stato, mentre i riquadri della barra di navigazione dimensioni e posizione della barra di navigazione. Ogni tipo di riquadro è composto da quattro dimensioni in pixel: in alto, a sinistra, a destra e in basso. Queste dimensioni specificano la distanza l'interfaccia utente di sistema si estende dai lati corrispondenti della finestra dell'app. Da evitare che si sovrappongono a quel tipo di UI di sistema, di conseguenza, l'UI dell'app deve essere inserita da quel tipo importo.
Questi tipi di intestazioni Android integrate sono disponibili tramite WindowInsets
:
I riquadri che descrivono le barre di stato. Si tratta delle barre dell'interfaccia utente di sistema in alto contenenti icone di notifica e altri indicatori. |
|
La barra di stato si inserisce quando sono visibili. Se al momento le barre di stato sono nascoste (a causa dell'attivazione della modalità a schermo intero immersiva), gli inserti della barra di stato principale saranno vuoti, ma non vuoti. |
|
Gli inserti che descrivono le barre di navigazione. Si tratta delle barre dell'interfaccia utente di sistema sul lato sinistro, destro o inferiore del dispositivo, che descrivono le icone della barra delle app o di navigazione. Questi possono cambiare in fase di esecuzione in base al metodo di navigazione preferito dall'utente e all'interazione con la barra delle app. |
|
La barra di navigazione viene inserita per indicare quando sono visibili. Se al momento le barre di navigazione sono nascoste (a causa dell'attivazione della modalità a schermo intero immersiva), gli inserti della barra di navigazione principale saranno vuoti, ma non vuoti. |
|
L'inserimento che descrive la decorazione della finestra dell'interfaccia utente di sistema se si trova in una finestra di forma libera, ad esempio la barra del titolo superiore. |
|
La barra dei sottotitoli viene inserita per indicare quando sono visibili. Se le barre dei sottotitoli codificati sono attualmente nascoste, gli inserti della barra dei sottotitoli codificati principali saranno vuoti, ma questi inserti non saranno vuoti. |
|
L'unione degli inserti della barra di sistema, che include le barre di stato, le barre di navigazione e la barra delle scritte. |
|
La barra di sistema viene inserita per indicare quando sono visibili. Se le barre di sistema sono attualmente nascoste (a causa dell'entrata in modalità a schermo intero immersiva), gli inserti della barra di sistema principale saranno vuoti, ma questi inserti non saranno vuoti. |
|
I riquadri che descrivono la quantità di spazio nella parte inferiore occupata dalla tastiera software. |
|
Gli inserti che descrivono lo spazio occupato dalla tastiera software prima dell'animazione della tastiera corrente. |
|
I riquadri che descrivono la quantità di spazio occupata dalla tastiera software dopo l'animazione corrente della tastiera. |
|
Un tipo di intestazioni che descrivono informazioni più dettagliate sull'interfaccia utente di navigazione, indicando la quantità di spazio in cui i "tocchi" verranno gestiti dal sistema e non dall'app. Per le barre di navigazione trasparenti con navigazione tramite gesti, alcuni elementi dell'app possono essere toccati tramite l'interfaccia utente di navigazione del sistema. |
|
L'elemento toccabile viene inserito quando questi sono visibili. Se gli elementi toccabili sono attualmente nascosti (a causa dell'attivazione della modalità schermo intero immersivo), i riquadri principali degli elementi toccabili saranno vuoti, ma non saranno vuoti. |
|
I riquadri che rappresentano la quantità di riquadri in cui il sistema intercetta i gesti per la navigazione. Le app possono specificare manualmente la gestione di un numero limitato di questi gesti tramite |
|
Un sottoinsieme di gesti di sistema che verranno sempre gestiti dal sistema e che non possono essere disattivati tramite |
|
Gli inserti che rappresentano la quantità di spaziatura necessaria per evitare la sovrapposizione con un ritaglio del display (tacca o foro). |
|
I riquadri che rappresentano le aree curve di una cascata. Un display a cascata presenta aree curve lungo i bordi dello schermo, dove lo schermo inizia a avvolgersi lungo i lati del dispositivo. |
Questi tipi sono riassunti in tre categorie "sicure" con inserti che garantiscono che i contenuti non oscurati:
Questi dati sono "sicuri" i tipi di inset proteggono i contenuti in diversi modi, in base ai elementi della piattaforma sottostanti:
- Utilizza
WindowInsets.safeDrawing
per proteggere i contenuti che non devono essere disegnati sotto l'interfaccia utente di sistema. Questo è l'utilizzo più comune degli inserti: per impedire di disegnare contenuti oscurati dall'interfaccia utente di sistema (parzialmente o completamente). - Usa
WindowInsets.safeGestures
per proteggere i contenuti con i gesti. Questo evita che i gesti di sistema siano in contrasto con i gesti delle app (ad esempio quelli per la parte inferiore dello schermo) fogli, caroselli o nei giochi). - Utilizza
WindowInsets.safeContent
come combinazione diWindowInsets.safeDrawing
eWindowInsets.safeGestures
per assicurarti i contenuti non hanno una sovrapposizione visiva o una sovrapposizione di gesti.
Configurazione inserti
Per dare all'app il pieno controllo su dove attinge i contenuti, segui questa configurazione passaggi. Senza questi passaggi, l'app potrebbe disegnare colori neri o a tinta unita dietro l'interfaccia utente di sistema o non essere animata in modo sincrono con la tastiera software.
- Scegli come target l'SDK 35 o versioni successive per applicare la modalità edge-to-edge su Android 15 e versioni successive. La tua app dietro l'interfaccia utente di sistema. Puoi modificare l'interfaccia utente dell'app gestendo gli inset.
- Se vuoi, chiama
enableEdgeToEdge()
traActivity.onCreate()
, che consente una protezione edge-to-edge della tua app rispetto alle versioni precedenti Versioni di Android. Imposta
android:windowSoftInputMode="adjustResize"
nella sezione Attività VoceAndroidManifest.xml
. Questa impostazione consente alla tua app di ricevere le dimensioni dell'IME del software come riquadri, che puoi usare per compilare e disporre i contenuti in modo appropriato quando l'IME appare e scompare nell'app.<!-- in your AndroidManifest.xml file: --> <activity android:name=".ui.MainActivity" android:label="@string/app_name" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.MyApplication" android:exported="true">
Componi API
Quando l'Attività ha assunto il controllo della gestione di tutti i riquadri, puoi usare Scrivi API per garantire che i contenuti non siano oscurati e che gli elementi interattivi non che si sovrappongono all'interfaccia utente di sistema. Queste API sincronizzano anche il layout dell'app con le modifiche dell'inserimento.
Ad esempio, questo è il metodo più semplice per applicare gli insert ai contenuti dell'intera app:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
Questo snippet applica i riquadri della finestra safeDrawing
come spaziatura interna al
l'intero contenuto dell'app. Sebbene ciò garantisca che gli elementi
che si sovrappongono all'interfaccia utente di sistema, significa anche che nessuna delle app verrà
all'interfaccia utente di sistema
per ottenere un effetto edge-to-edge. Per sfruttare appieno l'intero
devi perfezionare il punto in cui vengono applicati i riquadri su una schermata
o componente per componente.
Tutti questi tipi di riquadri sono animati automaticamente con animazioni IME con backporting all'API 21. Per estensione, tutti i layout che utilizzano questi riquadri sono anche l'animazione automatica quando cambiano i valori del riquadro.
Esistono due modi principali per utilizzare questi tipi di riquadri per regolare il contenuto layout: modificatori di spaziatura interna e modificatori di dimensione del riquadro.
Modificatori spaziatura interna
Modifier.windowInsetsPadding(windowInsets: WindowInsets)
applica i rientrati della finestra specificati come spaziatura interna, proprio come farebbe Modifier.padding
.
Ad esempio, Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
applica gli inserti di disegno sicuri come spaziatura su tutti e quattro i lati.
Esistono anche diversi metodi di utilità integrati per i tipi di intestazione più comuni.
Modifier.safeDrawingPadding()
è uno di questi metodi, equivalente a
Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
. Esistono modi di modificare analoghi per gli altri tipi di intestazione.
Modificatori di dimensione del riquadro
I seguenti modificatori applicano una quantità di rientranze della finestra impostando le dimensioni del componente sulle dimensioni delle rientranze:
Applica il lato iniziale di windowInsets come larghezza (ad esempio |
|
Applica il lato finale di windowInsets come larghezza (ad esempio |
|
Applica il lato superiore di windowInsets come altezza (ad esempio |
|
|
Applica il lato inferiore di windowInsets come altezza (ad esempio |
Questi modificatori sono particolarmente utili per determinare le dimensioni di un Spacer
che occupa lo spazio degli inserti:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Consumo inserito
I modificatori di spaziatura interna (windowInsetsPadding
e helper come
safeDrawingPadding
) utilizzano automaticamente la parte degli inserti che viene applicata come spaziatura interna. Approfondendo l'albero della composizione, i riquadri nidificati
modificatori di spaziatura interna e modificatori di dimensione del riquadro sa che alcune parti
i riquadri sono già stati utilizzati dai modificatori di spaziatura interna all'interno ed evita
usando la stessa porzione degli inserti più di una volta, il che provocherebbe anche
molto spazio in più.
Inoltre, i modificatori di dimensione degli insiemi evitano di utilizzare la stessa parte di riquadri più di una volta se sono già stati consumati dei riquadri. Tuttavia, poiché cambiano direttamente le loro dimensioni, non consumano gli insetti stessi.
Di conseguenza, l'annidamento dei modificatori di spaziatura modifica automaticamente la quantità di spaziatura applicata a ogni composable.
Se guardiamo lo stesso esempio di LazyColumn
di prima, LazyColumn
viene ridimensionato dal modificatore imePadding
. All'interno di LazyColumn
, l'ultimo elemento è
ridimensionate in base all'altezza della parte inferiore delle barre di sistema:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Quando l'IME è chiuso, il modificatore imePadding()
non applica spaziatura interna, poiché
l'IME non ha altezza. Poiché il modificatore imePadding()
non applica spaziatura interna,
non vengono utilizzati inset e l'altezza di Spacer
sarà uguale alla dimensione
del lato inferiore delle barre di sistema.
All'apertura dell'IME, i rispettivi riquadri si animano per corrispondere alle dimensioni dell'IME e
Il modificatore imePadding()
inizia ad applicare la spaziatura interna inferiore per ridimensionare
LazyColumn
all'apertura dell'IME. Quando il modificatore imePadding()
inizia ad applicare il padding inferiore, inizia anche a consumare questa quantità di rientri. Pertanto,
l'altezza di Spacer
inizia a diminuire, nell'ambito della spaziatura del sistema
barre è già stata applicata dal modificatore imePadding()
. Una volta che il modificatore imePadding()
applica una quantità di spaziatura inferiore maggiore rispetto alle barre di sistema, l'altezza di Spacer
è pari a zero.
Quando l'IME si chiude, le modifiche avvengono in modo inverso: Spacer
inizia a espandersi da un'altezza pari a zero quando imePadding()
viene applicato meno del lato inferiore delle barre di sistema, fino a quando Spacer
non corrisponde all'altezza del lato inferiore delle barre di sistema una volta che l'IME è completamente animato.
Questo comportamento viene ottenuto tramite la comunicazione tra tutti i modificatori windowInsetsPadding
e può essere influenzato in altri modi.
Modifier.consumeWindowInsets(insets: WindowInsets)
utilizza anche i riquadri
come Modifier.windowInsetsPadding
, ma non si applica
gli inserti consumati come spaziatura interna. È utile in combinazione con il riquadro
modificatori di dimensione, per indicare ai fratelli e sorelle che un certo numero di inserti ha
già consumato:
Column(Modifier.verticalScroll(rememberScrollState())) { Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars)) Column( Modifier.consumeWindowInsets( WindowInsets.systemBars.only(WindowInsetsSides.Vertical) ) ) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) } Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars)) }
Modifier.consumeWindowInsets(paddingValues: PaddingValues)
si comporta in modo molto simile alla versione con un argomento WindowInsets
, ma richiede un PaddingValues
arbitrario da consumare. È utile per informare
secondari quando la spaziatura interna o la spaziatura sono fornite da un meccanismo diverso da quello
modificatori di spaziatura interna inseriti, ad esempio un Modifier.padding
ordinario o l'altezza fissa
spaziatori:
Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
Se sono necessari gli intarsi della finestra non elaborati senza consumo, utilizza direttamente i valori WindowInsets
o WindowInsets.asPaddingValues()
per restituire un PaddingValues
degli intarsi non interessati dal consumo.
Tuttavia, a causa delle avvertenze riportate di seguito, è preferibile utilizzare la spaziatura interna degli riquadri delle finestre
e inseriscono i modificatori di dimensione nelle finestre, ove possibile.
Fasi di Jetpack Compose e Insets
Compose utilizza le API principali di AndroidX per aggiornare e animare i riquadri, che utilizzano le API della piattaforma sottostante per la gestione degli inserti. Per via di questa piattaforma, gli inserti hanno una relazione speciale con le fasi di Jetpack Scrivi.
Il valore degli insert viene aggiornato dopo la fase di composizione, ma prima della fase di layout. Ciò significa che la lettura del valore degli inserti nella composizione in genere utilizza un valore degli riquadri con un ritardo di un frame. I modificatori integrati descritti in questa pagina sono progettati per ritardare l'utilizzo dei valori degli inserti fino alla fase di layout, il che garantisce che i valori degli inserti vengano utilizzati nello stesso frame man mano che vengono aggiornati.
Animazioni IME della tastiera con WindowInsets
Puoi applicare Modifier.imeNestedScroll()
a un contenitore a scorrimento per aprire e
chiudi automaticamente l'IME quando scorri fino alla fine del contenitore.
class WindowInsetsExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) setContent { MaterialTheme { MyScreen() } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun MyScreen() { Box { LazyColumn( modifier = Modifier .fillMaxSize() // fill the entire window .imePadding() // padding for the bottom for the IME .imeNestedScroll(), // scroll IME at the bottom content = { } ) FloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp) // normal 16dp of padding for FABs .navigationBarsPadding() // padding for navigation bar .imePadding(), // padding for when IME appears onClick = { } ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add") } } }
Supporto integrato per i componenti Material 3
Per facilità d'uso, molti dei componenti componibili integrati in Material 3
(androidx.compose.material3
)
gestire gli elementi componibili autonomamente, in base al modo in cui gli elementi componibili sono posizionati nell'app
in base alle specifiche relative al materiale.
Composabili per la gestione degli intestazioni
Di seguito è riportato un elenco dei materiali Componenti che e gestire automaticamente gli inserti.
Barre delle app
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: applica i lati superiore e orizzontale delle barre di sistema come spaziatura interna poiché viene utilizzata nella parte superiore della finestra.BottomAppBar
: applica i lati inferiore e orizzontale delle barre di sistema come spaziatura interna.
Contenitori di contenuti
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(contenuti all'interno di un riquadro di navigazione modale a scomparsa): applica i riquadri verticale e avvia ai contenuti.ModalBottomSheet
: Applica i riquadri in basso.NavigationBar
: applica i rientri bottom e horizontal.NavigationRail
: applica i riquadri verticale e inizio.
Scaffold
Per impostazione predefinita,
Scaffold
fornisce degli inserti come parametro paddingValues
che puoi utilizzare e utilizzare.
Scaffold
non applica gli insert ai contenuti; questa responsabilità è tua.
Ad esempio, per consumare questi riquadri con LazyColumn
all'interno di un Scaffold
:
Scaffold { innerPadding -> // innerPadding contains inset information for you to use and apply LazyColumn( // consume insets as scaffold doesn't do it by default modifier = Modifier.consumeWindowInsets(innerPadding), contentPadding = innerPadding ) { items(count = 100) { Box( Modifier .fillMaxWidth() .height(50.dp) .background(colors[it % colors.size]) ) } } }
Sostituire gli inserti predefiniti
Puoi modificare il parametro windowInsets
passato al componibile in
per configurare il comportamento del componibile. Questo parametro può essere un tipo diverso di rientranza della finestra da applicare oppure può essere disattivato passando un'istanza vuota:WindowInsets(0, 0, 0, 0)
.
Ad esempio, per disattivare la gestione dei riquadri nelle
LargeTopAppBar
,
Imposta il parametro windowInsets
su un'istanza vuota:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Interoperabilità con gli inserti del sistema di visualizzazione
Potresti dover ignorare gli inserimenti predefiniti quando nella schermata sono presenti sia le visualizzazioni sia il codice di composizione nella stessa gerarchia. In questo caso, devi indicare esplicitamente quale deve utilizzare gli insert e quale ignorarli.
Ad esempio, se il layout più esterno è un layout della visualizzazione Android, devi utilizzare gli inserti nel sistema di visualizzazione e ignorarli per Compose.
In alternativa, se il layout più esterno è un composable, devi utilizzare gli inserti in Compose e aggiungere spaziatura ai composable AndroidView
di conseguenza.
Per impostazione predefinita, ogni ComposeView
utilizza tutti i riquadri al momento
Livello di consumo WindowInsetsCompat
. Per modificare questo comportamento predefinito, imposta
ComposeView.consumeWindowInsets
a false
.
Risorse
- Ora su Android: un'app per Android completamente funzionale creata interamente con Kotlin e Jetpack Compose.
- Gestire le applicazioni delle norme edge-to-edge in Android 15, un codelab che illustra l'applicazione delle norme edge-to-edge di Android 15
- 3 modi per migliorare l'esperienza con le app per Android: a schermo intero, tasto Indietro predittivo e Riepilogo: un video di YouTube che parla dell'applicazione forzata dello schermo intero in Android 15
- edge-to-edge e inserti | Suggerimenti per la scrittura: un video di YouTube che mostra come gestire i riquadri per disegnare da un bordo all'altro
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Componenti e layout di Material
- Eseguire la migrazione di
CoordinatorLayout
a Compose - Altre considerazioni