Compatibilidade com cortes da tela

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

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

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

Este documento descreve como implementar suporte em dispositivos com esses cortes, incluindo como trabalhar com a área de corte , ou seja, o retângulo de ponta a ponta 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 Corte da tela.

Escolher como o app processa áreas de corte

Para que seu conteúdo não se sobreponha a uma área de corte, geralmente é suficiente apenas garantir que o conteúdo não se sobreponha à barra de status e à barra de navegação. Se você estiver renderizando na área de corte, use WindowInsetsCompat.getDisplayCutout() para recuperar um objeto DisplayCutout que contenha as inserções e a caixa delimitadora seguras para cada corte. Essas APIs permitem verificar se o conteúdo se sobrepõe ao corte para que você possa reposicionar, se necessário.

Você também pode determinar se o conteúdo está disposto atrás da área de corte. O atributo de layout de janela layoutInDisplayCutoutMode controla como o conteúdo é desenhado na área de corte. Você pode 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 uma barra de sistema. Caso contrário, a janela não se sobrepõe ao corte da tela. Por exemplo, o conteúdo pode ser exibido com efeito letterbox quando mostrado no modo paisagem. Se o app for destinado ao SDK 35, isso será interpretado como ALWAYS para janelas não flutuantes.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS: o conteúdo sempre permitido se estender para as áreas de corte. Se o app for destinado ao SDK 35 e estiver em execução em um dispositivo Android 15, esse será o único modo permitido para janelas não flutuantes para garantir uma tela de ponta a ponta.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: o conteúdo é renderizado na área de corte nos modos retrato e paisagem. Não use para janelas flutuantes. Se o app for destinado 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 destinado ao SDK 35, isso será interpretado como ALWAYS para janelas não flutuantes.

Você pode definir o modo de corte de forma programática ou definindo um estilo na atividade. O exemplo a seguir define um estilo para aplicar o atributo LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES à 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 destinado ao SDK 35 e estiver em execução em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS será o comportamento padrão, e LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT será 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 destinado ao SDK 35 e estiver em execução em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES será interpretado como LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS para janelas não flutuantes.

Com LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, o conteúdo se estende até a área de corte na borda curta da tela, tanto no modo retrato quanto paisagem, independentemente de se as barras do sistema estão ocultas ou visíveis. Ao usar esse modo, verifique se nenhum conteúdo importante se sobrepõe à área de corte.

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

Imagem mostrando conteúdo renderizado na área de corte em modo retrato
Figura 2. Conteúdo renderizado na área de corte em modo retrato.

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

Imagem mostrando conteúdo renderizado na área de corte em modo paisagem
Figura 3. Conteúdo renderizado na área de corte em modo paisagem.

Nesse modo, a janela se estende sob os cortes na borda curta da tela, tanto no modo retrato quanto paisagem, independentemente de a janela estar ocultando as barras do sistema.

Considera-se que um corte no canto esteja na lateral pequena do dispositivo:

Imagem mostrando um dispositivo com um corte no canto
Figura 4. Um dispositivo com um corte no canto.

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

Se o app for destinado ao SDK 35 e estiver em execução em um dispositivo Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER será interpretado como LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS para janelas não flutuantes.

Com LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, nunca é permitido que a janela se sobreponha à área de corte.

A seguir, um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo retrato:

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

A seguir, um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo paisagem:

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

Práticas recomendadas para a compatibilidade com corte da tela

Ao trabalhar com cortes da tela, considere o seguinte:

  • Esteja atento ao posicionamento de elementos críticos da interface. Não deixe a área de corte obscurecer textos, controles ou outras informações importantes.
  • Não coloque ou estenda elementos interativos que exigem um bom reconhecimento de toque na área de corte. A sensibilidade ao toque pode ser menor na área de corte.
  • Sempre que possível, use WindowInsetsCompat para recuperar a altura da barra de status e determinar o preenchimento adequado a ser aplicado ao conteúdo. Evite codificar a altura da barra de status, porque isso pode levar à sobreposição ou ao corte do conteúdo.

    Uma imagem mostrando conteúdo cortado na parte de cima devido à configuração inadequada de encartes
    Figura 7. Use WindowInsetsCompat para evitar sobreposição ou corte de conteúdo.
  • Use View.getLocationInWindow() para determinar quanto espaço de janela o app está usando. Não suponha que o app esteja usando a janela inteira e não use View.getLocationOnScreen().

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

    Uma imagem mostrando o conteúdo se movendo para cima e para baixo durante as transições.
    Figura 8. Exemplo de conteúdo se movendo para cima e para baixo durante as transições.
  • No modo imersivo, tenha cuidado ao usar as coordenadas entre janela e tela, porque o app não ocupa a tela toda quando está com efeito letterbox. As coordenadas da origem da tela não são as mesmas que as da origem da janela devido ao efeito letterbox. Você pode transformar as coordenadas da tela em coordenadas da visualização, conforme necessário, usando getLocationOnScreen(). A imagem a seguir mostra como as coordenadas diferem quando o conteúdo está com efeito letterbox.

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

Testar como seu conteúdo é renderizado

Teste todas as telas e experiências do app. Se possível, teste em dispositivos com diferentes tipos de cortes. Se você não tiver um dispositivo com um corte, poderá simular configurações comuns de corte em qualquer dispositivo ou emulador que execute o Android 9 ou mais recente 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 o conteúdo é renderizado.

Outros recursos