Compatibilidade com cortes da tela

Teste 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, proporcionando espaço para sensores importantes na parte frontal do dispositivo.

O Android oferece suporte a cortes de 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 de tela em dispositivos com o Android 8.1 ou versões anteriores.

Este documento descreve como implementar suporte a dispositivos com 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 de tela na parte superior central
Figura 1. 1 Corte da tela.

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 é suficiente para garantir que ele 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 os encartes e a caixa delimitadora seguros para cada corte. Essas APIs permitem verificar se o conteúdo se sobrepõe ao corte para que você possa reposicionar, se necessário.

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

Você pode definir o modo de corte de forma programática ou definindo um estilo na sua atividade. O exemplo abaixo 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 em mais detalhes.

Comportamento padrão

Por padrão, no modo retrato sem sinalizações especiais definidas, a barra de status em um dispositivo com corte é redimensionada para ter pelo menos a mesma altura do corte, e o conteúdo é mostrado na área abaixo. No modo paisagem ou tela cheia, a janela do app tem efeito letterbox para que nenhum conteúdo seja mostrado na área de corte.

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

Para alguns conteúdos, como vídeos, fotos, mapas e jogos, a renderização na área de corte pode ser uma ótima maneira de proporcionar uma experiência mais imersiva e de ponta a ponta para os usuários. Com LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, o conteúdo se estende até a área de corte na borda curta da tela no modo retrato e paisagem, independentemente de as barras do sistema estarem ocultas ou visíveis. Ao usar esse modo, confira se nenhum conteúdo importante se sobrepõe à área de corte.

A imagem abaixo é um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES para um dispositivo na orientação retrato:

Uma imagem que mostra o conteúdo 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 a renderização de conteúdo na área de corte no modo paisagem
Figura 3. Renderização de conteúdo na área de corte no modo paisagem.

Nesse modo, a janela se estende por cortes na borda curta da tela nos modos retrato e paisagem, independente de a janela estar ocultando as barras do sistema.

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

Uma imagem que mostra um dispositivo com recorte de canto
Figura 4. Um dispositivo com corte no canto.

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

Com LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, a janela nunca pode se sobrepor à área de corte.

Confira abaixo um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no retrato:

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

Confira a seguir um exemplo de LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no modo paisagem:

Uma imagem mostrando LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER no 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 de tela, considere o seguinte:

  • Preste atenção no posicionamento de elementos críticos da interface. Não deixe a área de corte ocultar qualquer texto, controles ou outras informações importantes.
  • Não coloque nem estenda elementos interativos que exigem 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 padding adequado a ser aplicado ao conteúdo. Evite fixar a altura da barra de status no código, porque isso pode resultar em sobreposição ou corte de conteúdo.

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

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

    Uma imagem que mostra o conteúdo se movendo para cima e para baixo durante as transições.
    Figura 8. Exemplo de conteúdo que se move para cima e para baixo durante as transições.
  • No modo imersivo, tenha cuidado ao usar coordenadas de janela versus tela, já que o app não usa a tela inteira com efeito letterbox. As coordenadas da origem da tela não são iguais às da origem da janela devido ao efeito letterbox. É possível transformar as coordenadas da tela nas coordenadas da visualização, conforme necessário, usando getLocationOnScreen(). A imagem a seguir mostra como as coordenadas diferem quando o conteúdo tem efeito letterbox:

    Uma imagem que mostra as coordenadas de janela x tela quando o conteúdo tem efeito letterbox.
    Figura 9. Coordenadas de janela versus tela quando o conteúdo tem 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 corte. Se você não tem um dispositivo com um corte, pode simular configurações comuns em qualquer dispositivo ou emulador com o Android 9 ou versões mais recentes 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