Compatibilidade com cortes da tela

Testar o Compose
O Jetpack Compose é o kit de ferramentas de interface recomendado para Android. Aprenda a trabalhar com cortes de tela no Compose.

Um corte da tela é uma área em alguns dispositivos que se estende até a superfície da tela. Ele permite uma experiência de ponta a ponta deixando espaço para sensores importantes na parte frontal.

O Android oferece suporte a cortes de tela em dispositivos com o Android 9 (nível 28 da API) e mais alto. No entanto, os fabricantes de dispositivos também podem oferecer suporte a cortes da tela em dispositivos com Android 8.1 ou versão anterior.

Este documento descreve como implementar o suporte para dispositivos com cortes, incluindo como trabalhar com a área de corte, ou seja, de ponta a ponta retângulo na superfície da tela que contém o corte.

Uma imagem mostrando um exemplo de corte da tela na parte superior central
Figura 1. 1 Tela recorte.

Escolher como o app processa áreas de corte

Se você não quiser que seu conteúdo se sobreponha a uma área de corte, geralmente suficientes para que o conteúdo não se sobreponha à barra de status e ao barra de navegação. Se você estiver renderizando na área de corte, use WindowInsetsCompat.getDisplayCutout() para recuperar um objeto DisplayCutout que contém os encartes seguros e a caixa delimitadora para cada corte. Com essas APIs, você verifica se o conteúdo se sobrepõe ao recorte para que possa reposicionar, se necessário.

Você também pode determinar se o conteúdo está disposto atrás da área de corte. A layoutInDisplayCutoutMode O atributo de layout de janela controla como o conteúdo é desenhado na área de corte. É possível definir layoutInDisplayCutoutMode como um dos seguintes valores:

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT: o conteúdo é renderizado na área de corte quando o corte da tela está contido em um barra de sistema. Caso contrário, a janela não vai se sobrepor ao corte da tela. para exemplo, o conteúdo pode ter efeito letterbox quando exibido no modo paisagem. Se o app é direcionado ao SDK 35, isso será interpretado como ALWAYS para anúncios não flutuantes janelas.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS: o conteúdo sempre pode se estender para as áreas de recorte. Caso seu app seja destinado a SDK 35 e em execução em um dispositivo Android 15, esse é o único modo permitido para janelas não flutuantes para garantir uma exibição de ponta a ponta.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: o conteúdo é renderizado na área de corte nos modos retrato e paisagem. O que não fazer usar para janelas flutuantes. Se o app for direcionado ao SDK 35, isso será interpretado como ALWAYS para janelas não flutuantes.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER: o conteúdo nunca é renderizado na área de corte. Se o app for direcionado ao SDK 35, esse será interpretado como ALWAYS para janelas não flutuantes.

É possível definir o modo de corte de maneira programática ou definindo um style em sua atividade. O seguinte define um estilo para aplicar a LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES atributo à atividade.

<style name="ActivityTheme">
  <item name="android:windowLayoutInDisplayCutoutMode">
    shortEdges <!-- default, shortEdges, or never -->
  </item>
</style>

As seções a seguir descrevem os diferentes modos de corte com mais detalhes.

Comportamento padrão

Se o app for direcionado ao SDK 35 e estiver sendo executado em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS é o comportamento padrão. LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT é interpretado como LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS para janelas não flutuantes.

Caso contrário, LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT será o padrão.

Renderizar conteúdo em áreas de corte de borda curta

Se o app for direcionado ao SDK 35 e estiver sendo executado em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES é interpretado como LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS para janelas não flutuantes.

Com o LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, os se estende para a área de corte na borda curta da tela nos dois retrato e paisagem, independentemente de as barras do sistema estarem ocultas ou visíveis. Ao usar esse modo, certifique-se de que nenhum conteúdo importante se sobreponha a área de corte.

A imagem abaixo é um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES para um dispositivo no modo retrato:

Uma imagem que mostra o conteúdo sendo renderizado na área de corte no modo retrato
Figura 2. Renderização de conteúdo na área de corte no modo retrato.

A imagem abaixo é um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES para um dispositivo no modo paisagem:

Uma imagem que mostra o conteúdo sendo renderizado na área de corte no modo paisagem
Figura 3. Renderização de conteúdo na área de corte no modo paisagem.

Neste modo, a janela se estende por baixo dos cortes na borda curta da tela nos modos retrato e paisagem, não importa se a janela está ocultando barras de sistema.

Considera-se que há um corte no canto da borda curta:

Uma imagem mostrando um dispositivo com um corte de canto
Figura 4. Um dispositivo com um corte de canto.

Nunca renderize conteúdo na área de corte da tela

Se o app for direcionado ao SDK 35 e estiver sendo executado em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER é interpretado como LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS para janelas não flutuantes.

Com o LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, a janela nunca tem permissão para se sobreponham à área de corte.

Este é um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no retrato:

Uma imagem mostrando o LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo retrato
Figura 5. Exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER para o modo retrato.

Este é um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo paisagem:

Uma imagem mostrando o LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER para o modo paisagem
Figura 6. Exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo paisagem.

Práticas recomendadas para a compatibilidade com corte de tela

Ao trabalhar com cortes da tela, considere o seguinte:

  • Esteja atento ao posicionamento dos elementos essenciais da IU. Não deixe a área de corte oculta qualquer texto, controles ou outras informações importantes.
  • Não coloque ou estenda elementos interativos que exijam toques minuciosos na área de corte. A sensibilidade ao toque pode ser menor no área de corte.
  • Sempre que possível, use WindowInsetsCompat para recuperar a altura da barra de status e determinar o padding apropriado a ser aplicado ao seu conteúdo. Evite fixar a altura da barra de status no código, porque isso pode causar conteúdos sobrepostos ou cortados.

    Uma imagem mostrando conteúdo cortado na parte de cima devido à configuração incorreta de encartes
    Figura 7. Use o WindowInsetsCompat para evite sobrepor ou cortar o conteúdo.
  • Usar View.getLocationInWindow() para determinar quanto espaço da janela seu app está usando. Não presuma que o app está usando a janela inteira, e não use View.getLocationOnScreen()

  • Use os modos de corte always, shortEdges ou never se o app precisar para entrar e sair do modo imersivo. O comportamento de corte padrão pode fazer conteúdo do app seja renderizado na área de corte enquanto as barras de sistema estão presente, mas não no modo imersivo. Isso faz o conteúdo subir e para baixo durante as transições, conforme demonstrado no exemplo a seguir.

    Uma imagem que mostra conteúdo indo para cima e para baixo durante as transições.
    Figura 8. Exemplo de movimento para cima e para baixo durante as transições.
  • No modo imersivo, tenha cuidado ao usar as coordenadas de janela versus tela, pois o app não usa a tela inteira quando está com efeito letterbox. Devido à com efeito letterbox, as coordenadas da origem da tela não são as mesmas que as coordenadas da origem da janela. Você pode transformar coordenadas da tela no coordenadas conforme necessário usando getLocationOnScreen(). A imagem a seguir mostra como as coordenadas diferem quando o conteúdo tem efeito letterbox:

    Uma imagem mostrando as coordenadas de janela e tela quando o conteúdo está com efeito letterbox.
    Figura 9. Coordenadas de janela versus tela quando com efeito letterbox.
  • Ao processar MotionEvent, use MotionEvent.getX() e MotionEvent.getY() para evitar problemas de coordenadas semelhantes. Não usar MotionEvent.getRawX() ou MotionEvent.getRawY()

Testar como seu conteúdo é renderizado

Teste todas as telas e experiências do seu app. Testar em dispositivos com diferentes tipos de corte, se possível. Se você não tem um dispositivo com recorte, é possível simular configurações comuns de corte em qualquer dispositivo ou emulador com Android 9 ou superior fazendo o seguinte:

  1. Ative as Opções do desenvolvedor.
  2. Na tela Opções do desenvolvedor, role para baixo até a seção Desenho e selecione Simular uma tela com corte.
  3. Selecione o tipo de corte.

    Uma imagem mostrando como simular um corte da tela no emulador
    Figura 10. Opções do desenvolvedor para testar como seu o conteúdo é renderizado.

Outros recursos