Garanta a compatibilidade com a navegação por gestos

A partir do Android 10 (nível 20 da API), o sistema Android é totalmente compatível com a navegação com base em gestos. Há duas coisas que os desenvolvedores precisam fazer para garantir que os apps sejam compatíveis com esse recurso:

  • Estender o conteúdo do app de ponta a ponta na tela
  • Resolver conflitos de gestos do app

Conteúdo do app de ponta a ponta

Para aproveitar o espaço adicional na tela disponibilizado pela barra de navegação flutuante, você precisa fazer algumas alterações no seu app.

Configurar barras do sistema transparentes

Para fazer isso, configure os seguintes valores no seu tema:

<!-- values-29/themes.xml: -->

    <style name="AppTheme" parent="...">
        <item name="android:navigationBarColor">@android:color/transparent</item>

        <!-- Optional, but recommended for full edge-to-edge rendering -->
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
    
Barra de navegação transparente com botões ativados.

Também é possível fazer isso de forma dinâmica. Para isso, use Window.setNavigationBarColor() e Window.setStatusBarColor().

Quando o dispositivo está definido para usar a navegação por gestos e você faz com que o segundo plano da barra de navegação do app fique transparente, o sistema atualiza automaticamente a cor da alça com base na cor do conteúdo por trás dela. No entanto, quando o usuário está no modo de navegação com dois ou três botões, esses botões não mudam de cor. Em vez disso, o sistema aplica um segundo plano translúcido para que os botões fiquem visíveis. No entanto, o sistema só poderá fazer isso se o app for direcionado ao nível de API 29 ou mais recente.

Configurar o sinalizador de visibilidade da IU

Para exibir sua visualização de ponta a ponta, seu app precisa informar ao sistema que o app pode processar essa visualização. Para fazer isso, use View.setSystemUiVisibility() para definir os sinalizadores a seguir:

Kotlin

    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
    

Java

    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    

Juntos, esses sinalizadores informam ao sistema que seu app deve ser exibido em tela cheia e como se as barras de navegação e de status não estivessem presentes. Para outros eventos em tela cheia, defina SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, que permite desenhar atrás da barra de status.

Se você estiver usando uma classe de visualização como CoordinatorLayout ou DrawerLayout, que gerencia automaticamente a barra de status, os sinalizadores SYSTEM_UI_FLAG_LAYOUT_STABLE e SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN já podem estar definidos. Além disso, caso esteja usando setSystemUiVisibility() para definir outros sinalizadores, como SYSTEM_UI_FLAG_IMMERSIVE, tome cuidado para que esses outros sinalizadores não substituam os mencionados acima.

Mesmo que o app use uma visualização de ponta a ponta, o sistema ainda usará a API WindowInsets para indicar onde estão as barras do sistema.

Processar encartes manualmente

Se o app usa uma hierarquia de visualização personalizada, talvez seja necessário processar manualmente encartes de janela do sistema. Normalmente, isso é feito por meio da implementação de uma interface OnApplyWindowInsetsListener:

Kotlin

    view.setOnApplyWindowInsetsListener() {v, insets ->
        insets.consumeSystemWindowInsets()
    

Java

    view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
        @Override
        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
            // 1. Move views on top edge down by insets.getSystemWindowInsetTop()
            // 2. Move views on bottom edge up by insets.getSystemWindowInsetBottom()
            // 3. Also check getSystemWindowInsetLeft/Right(), such as for landscape
            // orientations
            return insets.consumeSystemWindowInsets();
        }
    });
    

WindowInsets fornece encartes visuais comuns para todas as barras do sistema por meio de getSystemWindowInsets(). Além disso, o Android 10 acrescenta os seguintes métodos a WindowInsets:

Como resolver conflitos de gestos do app

O modelo de navegação por gestos pode entrar em conflito com gestos usados anteriormente pelos desenvolvedores de apps. Por isso, talvez seja necessário fazer ajustes na interface do usuário do seu app.

Conflitos com gestos "Voltar"

O novo gesto "Voltar" do sistema é um deslizamento de fora para dentro a partir da borda esquerda ou direita. Isso pode interferir nos elementos de navegação do app nessas áreas. Para manter a funcionalidade dos elementos nas bordas esquerda e direita da tela, será necessário desativar o gesto "Voltar" criteriosamente, indicando ao sistema quais regiões precisam receber a entrada por toque. Para fazer isso, transmita uma List<Rect> para a API View.setSystemGestureExclusionRects() introduzida no Android 10. Esse método também está disponível em ViewCompat desde o androidx.core:core:1.1.0-dev01.

Exemplo:

Kotlin

    var exclusionRects = listOf(rect1, rect2, rect3)

    fun onLayout(
            changedCanvas: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
      // Update rect bounds and the exclusionRects list
      setSystemGestureExclusionRects(exclusionRects)
    }

    fun onDraw(canvas: Canvas) {
      // Update rect bounds and the exclusionRects list
      setSystemGestureExclusionRects(exclusionRects)
    }
    

Java

    List<Rect> exclusionRects;

    public void onLayout(
            boolean changedCanvas, int left, int top, int right, int bottom) {
        // Update rect bounds and the exclusionRects list
        setSystemGestureExclusionRects(exclusionRects);
    }

    public void onDraw(Canvas canvas) {
        // Update rect bounds and the exclusionRects list
        setSystemGestureExclusionRects(exclusionRects);
    }
    

Conflitos com os gestos de Tela inicial/Alternância rápida

Os novos gestos do sistema para a Tela inicial e Alternância rápida envolvem deslizamentos na parte inferior da tela, no espaço anteriormente ocupado pela barra de navegação. Os apps não podem desativar esses gestos, como acontece com o gesto "Voltar".

Para mitigar esse problema, o Android 10 introduz a API WindowInsets.getMandatorySystemGestureInsets(), que informa aos apps os limites de reconhecimento de toque.

Jogos e outros apps sem visualização

Jogos e outros apps que não têm uma hierarquia de visualização geralmente exigem que o usuário deslize perto das áreas de gesto do sistema. Nesses casos, os jogos podem usar Window.setSystemGestureExclusionRects() para excluir áreas que se sobrepõem a regiões reservadas para os gestos do sistema. Os jogos têm que garantir a exclusão dessas áreas somente quando necessário, como durante o jogo.

Se o jogo precisa que o usuário deslize perto da área de gestos de início, o app pode solicitar execução no modo imersivo. Isso desativará os gestos do sistema enquanto o usuário estiver interagindo com o jogo, mas também permitirá que ele reative os gestos do sistema deslizando de baixo para cima na tela.

Outros recursos

Para saber mais sobre a navegação por gestos, consulte os recursos adicionais a seguir:

Postagens do blog

Vídeos