A plataforma Android é responsável por desenhar a IU do sistema, como o barra de status e de navegação. Essa interface do sistema é exibida, independentemente app que o usuário está usando.
WindowInsets
fornece informações sobre o sistema.
interface para garantir que o app desenhe na área correta e não fique obscurecida
pela IU do sistema.
No Android 14 (nível 34 da API) e versões anteriores, a interface do app não é mostrada abaixo da tela as barras de sistema e cortes da tela por padrão.
No Android 15 (nível 35 da API) e versões mais recentes, o app é renderizado abaixo do sistema barras e cortes de tela quando o app for direcionado ao SDK 35. Isso resulta em um uma experiência do usuário perfeita e permite que seu aplicativo aproveite ao máximo a espaço disponível na janela.
A exibição de conteúdo por trás da IU do sistema é chamada de de ponta a ponta. Neste você aprende sobre os diferentes tipos de encarte, como passar de ponta a ponta, e como usar as APIs de encarte para animar a interface e garantir que o conteúdo do app não seja ocultado por elementos da interface do sistema.
Princípios básicos do encarte
Quando um aplicativo vai de ponta a ponta, você precisa garantir que o conteúdo importante e interações não são obscurecidas pela interface do sistema. Por exemplo, se um botão for colocado atrás da barra de navegação, talvez o usuário não consiga clicar nele.
O tamanho da interface do sistema e as informações sobre onde ela é colocada são especificados por encartes.
Cada parte da interface do sistema tem um tipo correspondente de encarte que descreve o tamanho e onde é colocado. Por exemplo, os encartes da barra de status fornecem o tamanho e a posição da barra de status, enquanto os encartes da barra de navegação fornecem tamanho e posição da barra de navegação. Cada tipo de encarte consiste em quatro dimensões em pixels: superior, esquerda, direita e inferior. Essas dimensões especificam até onde a interface do sistema se estende dos lados correspondentes da janela do app. Para evitar sobreposta a esse tipo de interface do sistema. Portanto, a interface do app precisa ser inserida de dados.
Esses tipos de encarte integrados do Android estão disponíveis pelo WindowInsets
:
Encartes que descrevem as barras de status. Essas são as barras de interface superiores do sistema que contêm ícones de notificação e outros indicadores. |
|
Os encartes da barra de status para quando ficam visíveis. Se as barras de status estiverem escondidas no momento (devido ao entrar no modo de tela cheia imersivo), os encartes da barra de status principal vão estar vazios, mas esses encartes não vão estar vazios. |
|
Encartes que descrevem as barras de navegação. Essas são as barras de IU do sistema no lado esquerdo, direito ou inferior do dispositivo, que descrevem a barra de tarefas ou os ícones de navegação. Eles podem mudar durante a execução com base no método de navegação preferido do usuário e na interação com a barra de tarefas. |
|
Os encartes da barra de navegação para quando ficam visíveis. Se as barras de navegação estiverem escondidas no momento (devido ao entrar no modo de tela cheia imersivo), os encartes da barra de navegação principal vão estar vazios, mas esses encartes não vão estar vazios. |
|
O encarte descrevendo a decoração da janela da interface do sistema se estiver em uma janela de formato livre, como a barra de título superior. |
|
Os encartes da barra de legenda para quando estão visíveis. Se as barras de legenda estiverem ocultas no momento, os encartes da barra de legenda principal estarão vazios, mas não estarão. |
|
A união dos encartes da barra do sistema, que incluem as barras de status, de navegação e de legenda. |
|
Os encartes da barra do sistema para quando ficam visíveis. Se as barras de sistema estiverem escondidas no momento (devido ao entrar no modo de tela cheia imersivo), os encartes da barra de sistema principal vão estar vazios, mas esses encartes não vão estar. |
|
Os encartes que descrevem a quantidade de espaço na parte inferior que o teclado de software ocupa. |
|
Os encartes que descrevem a quantidade de espaço que o teclado de software ocupava antes da animação do teclado atual. |
|
Os encartes que descrevem a quantidade de espaço que o teclado de software vai ocupar após a animação do teclado atual. |
|
Um tipo de encarte que descreve informações mais detalhadas sobre a interface de navegação, indicando a quantidade de espaço em que o "toca" serão processados pelo sistema, não pelo aplicativo. Para barras de navegação transparentes com navegação por gestos, é possível tocar em alguns elementos do app na interface de navegação do sistema. |
|
Os encartes de elemento tocável para quando ficam visíveis. Se os elementos tocáveis estiverem ocultos (devido ao entrar no modo de tela cheia imersivo), os encartes principais do elemento tocável vão estar vazios, mas esses encartes não vão estar. |
|
Os encartes que representam a quantidade de encartes em que o sistema vai interceptar gestos para navegação. Os apps podem especificar manualmente o processamento de uma quantidade limitada desses gestos usando o |
|
Um subconjunto dos gestos do sistema que sempre serão processados e que não podem ser desativados pelo |
|
Os encartes representam o espaçamento necessário para evitar a sobreposição com um corte da tela (entalhe ou pinhole). |
|
Encartes que representam as áreas curvas de uma exibição em cascata. Uma tela em cascata tem áreas curvas ao longo das bordas, onde a tela começa a se envolver nas laterais do dispositivo. |
Esses tipos são resumidos em três tipos de encarte que garantem que o conteúdo obscurecidos:
Esses anúncios os tipos de encarte protegem o conteúdo de diferentes maneiras, com base encartes de plataforma subjacentes:
- Use
WindowInsets.safeDrawing
para proteger conteúdo que não pode ser desenhado em qualquer IU do sistema. Este é o uso mais comum de encartes: para evitar mostrar conteúdo oculto pela interface do sistema (parcialmente ou completamente). - Use
WindowInsets.safeGestures
para proteger o conteúdo com gestos. Isso evita que os gestos do sistema entrem em conflito com os gestos do aplicativo (como os de baixo folhas, carrosséis ou jogos). - Use
WindowInsets.safeContent
como uma combinação deWindowInsets.safeDrawing
eWindowInsets.safeGestures
para garantir o conteúdo não tem sobreposição visual e de gestos.
Configuração de encartes
Para permitir que o app tenha controle total sobre onde ele desenha conteúdo, siga estas configurações etapas. Sem essas etapas, o app pode desenhar cores pretas ou sólidas por trás do interface do sistema ou não anime de forma síncrona com o teclado de software.
- Direcione o SDK 35 ou mais recente para aplicar de ponta a ponta no Android 15 e versões mais recentes. Seu app é mostrado por trás da IU do sistema. É possível ajustar a interface do seu app lidando encartes.
- Opcionalmente, chame
enableEdgeToEdge()
emActivity.onCreate()
, que permite que o app fique de ponta a ponta sobre os Versões do Android. Defina
android:windowSoftInputMode="adjustResize"
nas suas atividades EntradaAndroidManifest.xml
. Esta configuração permite que o app receba o tamanho do IME de software como encartes, que podem ser usados para preencher e posicionar o conteúdo quando o IME aparecer e desaparecer do 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">
APIs do Compose
Quando a atividade assumir o controle do processamento de todos os encartes, você poderá usar o Compose. APIs para garantir que o conteúdo não seja ocultado e que elementos interativos não sejam se sobreponham à IU do sistema. Essas APIs também sincronizam o layout do app com alterações de encarte.
Por exemplo, esse é o método mais básico de aplicar os encartes ao conteúdo de todo o app:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
Esse snippet aplica os encartes da janela safeDrawing
como padding ao redor da
todo o conteúdo do app. Isso garante que os elementos interativos não
se sobreponham à IU do sistema, isso também significa que nenhum aplicativo será desenhado
a IU do sistema para obter um efeito de ponta a ponta. Para aproveitar ao máximo
você precisa ajustar onde os encartes são aplicados em uma tela, tela por tela.
ou componente por componente.
Todos esses tipos de encarte são animados automaticamente com animações do IME backport para a API 21. Por extensão, todos os seus layouts que usam esses encartes são que também são animados automaticamente à medida que os valores do encarte mudam.
Há duas maneiras principais de usar esses tipos de encarte para ajustar o elemento combinável. Layouts: modificadores de padding e modificadores de tamanho de encarte.
Modificadores de padding
Modifier.windowInsetsPadding(windowInsets: WindowInsets)
aplica o
encartes de janela fornecidos como padding, agindo da mesma forma que o Modifier.padding
faria.
Por exemplo, Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
se aplica
o encarte seguro do desenho como padding nos quatro lados.
Há também vários métodos utilitários integrados para os tipos de encarte mais comuns.
Modifier.safeDrawingPadding()
é um desses métodos, equivalente a
Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
. Há
modificadores para os outros tipos de encarte.
Modificadores de tamanho de encarte
Os seguintes modificadores aplicam uma série de encartes de janela definindo o tamanho que o componente seja o tamanho dos encartes:
Aplica o lado inicial de windowInsets como a largura (como |
|
Aplica o lado final de windowInsets como a largura (como |
|
Aplica o lado superior de windowInsets como a altura (como |
|
|
Aplica o lado de baixo de windowInsets como a altura (como |
Esses modificadores são especialmente úteis para dimensionar um Spacer
que ocupa
de encartes:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Consumo inserido
Os modificadores de padding do encarte (windowInsetsPadding
e auxiliares como
safeDrawingPadding
) consomem automaticamente a parte dos encartes que são
aplicado como padding. Ao se aprofundar na árvore de composição, o encarte aninhado
modificadores de padding e de tamanho
do encarte sabem que uma parte dos
já foram consumidos por modificadores de padding externos e evitam
usar a mesma parte dos encartes mais de uma vez, o que resultaria em
muito espaço extra.
Os modificadores de tamanho de encarte também evitam o uso da mesma parte de encartes mais de uma vez se os encartes já tiverem sido consumidos. No entanto, como estão mudando tamanho diretamente, eles não consomem encartes.
Como resultado, o aninhamento de modificadores de padding muda automaticamente a quantidade de padding aplicado a cada elemento combinável.
Analisando o mesmo exemplo de LazyColumn
de antes, o LazyColumn
está sendo
redimensionado pelo modificador imePadding
. Dentro de LazyColumn
, o último item é
dimensionada para ser a altura da parte inferior das barras do sistema:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Quando o IME é fechado, o modificador imePadding()
não aplica padding, já que
o IME não tem altura. Como o modificador imePadding()
não está aplicando padding,
nenhum encarte será consumido, e a altura do Spacer
será o tamanho do
na parte de baixo das barras do sistema.
Quando o IME é aberto, os encartes do IME são animados para corresponder ao tamanho do IME, e o
O modificador imePadding()
começa a aplicar o padding de baixo para redimensionar o
LazyColumn
quando o IME é aberto. Quando o modificador imePadding()
começa a ser aplicado
o padding da parte de baixo também começa a consumir essa quantidade de encartes. Portanto, a
A altura do Spacer
começa a diminuir, como parte do espaçamento do sistema.
barras já foi aplicada pelo modificador imePadding()
. Quando o
O modificador imePadding()
está aplicando uma quantidade maior de padding inferior
que as barras do sistema, a altura da Spacer
é zero.
Quando o IME é fechado, as alterações acontecem no sentido inverso: o Spacer
começa a
se expandir a partir de uma altura de zero quando a imePadding()
estiver aplicando menos que o
na parte de baixo das barras do sistema, até que finalmente a Spacer
corresponda à altura
na parte inferior das barras do sistema depois que o IME estiver completamente animado.
Esse comportamento é alcançado por meio da comunicação entre todas
windowInsetsPadding
e pode ser influenciada em alguns outros
de várias formas.
Modifier.consumeWindowInsets(insets: WindowInsets)
também consome encartes
da mesma forma que Modifier.windowInsetsPadding
, mas isso não se aplica
os encartes consumidos como padding. Isso é útil junto com o encarte
modificadores de tamanho para indicar a irmãos que uma certa quantidade de encartes
já foi consumido:
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)) }
O Modifier.consumeWindowInsets(paddingValues: PaddingValues)
se comporta muito
semelhante à versão com um argumento WindowInsets
, mas pega uma
PaddingValues
arbitrário para consumo. Isso é útil para informar
filhos quando o preenchimento ou o espaçamento é fornecido por algum outro mecanismo além do
Modificadores de encarte de padding, como um Modifier.padding
comum ou uma altura fixa
espaçadores:
@OptIn(ExperimentalLayoutApi::class) Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
Nos casos em que os encartes de janela brutos forem necessários sem consumo, use o método
WindowInsets
diretamente ou use WindowInsets.asPaddingValues()
para
retornar uma PaddingValues
dos encartes que não são afetados pelo consumo.
No entanto, devido às ressalvas abaixo, prefira usar o padding de encartes de janela.
e encarte de janela sempre que possível.
Encartes e fases do Jetpack Compose
O Compose usa as principais APIs do AndroidX para atualizar e animar encartes, que usam as APIs de plataforma subjacentes para gerenciar encartes. Por causa dessa plataforma os encartes têm uma relação especial com as fases do Jetpack Compose.
O valor dos encartes é atualizado após a fase de composição, mas antes da fase de layout. Isso significa que ler o valor dos encartes na composição geralmente usa um valor dos encartes que está um frame atrasado. O modelo os modificadores descritos nesta página foram criados para atrasar o uso dos valores do elemento é inserido até a fase de layout, que garante que os valores de encarte sejam usados mesmo frame que são atualizados.
Animações do IME do teclado com WindowInsets
Você pode aplicar Modifier.imeNestedScroll()
a um contêiner de rolagem para abrir e
feche o IME automaticamente ao rolar para a parte inferior do contêiner.
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") } } }
Suporte a encarte para os componentes do Material 3
Para facilitar o uso, muitos dos elementos combináveis do Material 3 integrados
(androidx.compose.material3
)
processar encartes por conta própria, com base em como os elementos combináveis são colocados no app.
de acordo com as especificações do material.
Inserção no processamento de elementos combináveis
Abaixo está uma lista de materiais componentes que para lidar automaticamente com encartes.
Barras de apps
TopAppBar
/SmallTopAppBar
CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: aplica as laterais superior e horizontal das barras do sistema como padding, já que elas são usadas na parte de cima da janela.BottomAppBar
: aplica as laterais inferior e horizontais das barras do sistema como padding.
Contêineres de conteúdo
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(conteúdo dentro de uma gaveta de navegação modal): aplica encartes vertical e início ao conteúdo.ModalBottomSheet
Aplica os encartes inferiores.NavigationBar
: aplica os encartes inferior e horizontais.NavigationRail
: aplica os encartes de vertical e início.
Scaffold
Por padrão,
Scaffold
fornece encartes como parâmetro paddingValues
para você consumir e usar.
Scaffold
não aplica os encartes ao conteúdo. essa responsabilidade é sua.
Por exemplo, para consumir esses encartes com um LazyColumn
dentro de um 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]) ) } } }
Substituir encartes padrão
É possível mudar o parâmetro windowInsets
transmitido ao elemento combinável para
configurar o comportamento da função de composição. Esse parâmetro pode ser um tipo diferente de
encarte de janela para aplicar ou desativado ao transmitir uma instância vazia:
WindowInsets(0, 0, 0, 0)
:
Por exemplo, para desativar o processamento do encarte em
LargeTopAppBar
,
Defina o parâmetro windowInsets
como uma instância vazia:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Interoperabilidade com encartes do sistema de visualização
Pode ser necessário substituir os encartes padrão quando a tela tiver visualizações e Escreva o código na mesma hierarquia. Nesse caso, você precisa ser explícito em qual deles deve consumir os encartes e qual deve ignorá-los.
Por exemplo, se o layout mais externo for um layout de visualização do Android, você deverá
consumir os encartes no sistema de visualização e ignorá-los no Compose.
Como alternativa, caso o layout mais externo seja um elemento combinável, consuma o elemento
encartes no Compose e preencha os elementos combináveis AndroidView
adequadamente.
Por padrão, cada ComposeView
consome todos os encartes no
Nível de consumo WindowInsetsCompat
. Para alterar esse comportamento padrão, defina
ComposeView.consumeWindowInsets
para false
.
Recursos
- Now in Android: um app Android totalmente funcional criado inteiramente com Kotlin e Jetpack Compose.
- Processar restrições de ponta a ponta no Android 15: um codelab que explica a aplicação de ponta a ponta do Android 15.
- Três coisas para melhorar sua experiência no app Android: de ponta a ponta, volta preditiva e resumo: um vídeo do YouTube sobre a aplicação de ponta a ponta do Android 15.
- De ponta a ponta e encartes | Dicas de escrita: um vídeo do YouTube que mostra como processar encartes para desenhar de ponta a ponta
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Componentes e layouts do Material Design
- Migrar
CoordinatorLayout
para o Compose - Outras considerações