Construindo uma Bottom Navigation com Kotlin e Android JetPack

Lucca Beurmann
10 min readFeb 22, 2021

--

Mascote do Android voando no céu com uma mochila à jato, correlacionando com o nome da iniciativa Android JetPack.

Construa um componente sólido de maneira ágil e utilizando as bibliotecas desenvolvidas pela Google para eliminar código boilerplate.

Uma breve introdução ao Bottom Navigation

Bottom Navigation é um componente de interface utilizado para que o usuário consiga navegar facilmente por diferentes seções sem necessariamente ter que trocar de tela, grandes aplicativos como Spotify, Instagram, Twitter e muitos outros já utilizam essa abordagem de navegação por uma série de motivos, sendo o principal deles o conforto que é gerado para o usuário final, já que a forma que seguramos os smartphones favorece que esse componente seja confortavelmente utilizado pelos dedões.

Exemplo de Bottom Navigation: Uma barra de cor roxa posicionado no extremo inferior da tela cobrindo toda a largura da mesma e contendo 4 ícones de navegação.

Os princípios da Bottom Navigation

Assim como existem uma série de razões para se implementar uma Bottom Navigation também existem uma série de “regras” para a utilização das mesmas, segundo a documentação do MaterialUI esse componente se baseia em 3 pilares: Ergonomia, Consistência e Igualdade.

3 cards verdes contendo os 3 princípios da Bottom Navigation, em inglês: Ergonomic, Consistent e Related.
  • Ergonomia: O princípio da ergonomia diz que todas as implementações de um Bottom Navigation devem estar posicionados em um local confortável para a utilização do usuário, e que os ícones devem estar devidamente separados por uma distância segura a fim de evitar cliques indesejados.
  • Consistência: O princípio da consistência diz que todas as implementações de um Bottom Navigation devem estar sempre na parte de baixo da tela e devem usar a mesma formatação .
  • Igualdade: O princípio da igualdade diz que todos os ícones presentes em uma Bottom Navigation devem possuir a mesma importância dentro do aplicativo, e não devem ser usados para telas de configuração ou preferências do usuário.

Implementando um Bottom Navigation

Para demonstrar a implementação do Bottom Navigation View iremos utilizar um projeto construído do zero única e exclusivamente voltado para esse fim, mas entenda que até o fim desse artigo você deverá ser capaz de implementar essa funcionalidade em um projeto já existente.

Nosso projeto recém criado possui apenas um arquivo que realmente nos interessa: A Main Activity que, no momento, ainda não possui nenhuma funcionalidade implementada.

Adicionando o componente via XML

Para adicionar um Bottom Navigation para nossa Activity iremos até seu respectivo XML e lá declararemos nosso componente, é importante salientar que esse componente só estará disponível caso seu projeto esteja com a biblioteca Material devidamente atualizada.

XML da Main Activity após implementar a Bottom Navigation View

Após fazer essa adição ao XML vemos que na preview nossa navigation ainda não possui cor de fundo nem itens para preenche-la, nessa demonstração não iremos alterar a cor de fundo do componente mas caso você queira alterá-la basta definir uma cor XML ou Hexadecimal na propriedade background.

Configurando o menu da Bottom Navigation

Para adicionar itens na nossa barra de navegação precisaremos criar um XML do tipo menu e caso o seu projeto não tenha um subdiretório menu na pasta res basta criá-lo:

  1. Clique com o botão direito na pasta res
  2. Clique na opção New -> Android Resource Directory
  3. Em resource type selecione menu
  4. Clique em ok

Agora no diretório menu crie um novo menu resource file e nomeie-o como quiser, nessa demonstração chamaremos de menu_bottom_nav.

Estado inicial do XML menu.

O estado inicial do XML é uma tag menu sem nenhum conteúdo e para adicionarmos itens ao nosso menu basta preencher o corpo de <menu> com n tags <item/>, mas tenha em mente que o número máximo de itens em um bottom navigation é 5, enquanto o mínimo é 3.

Adicionaremos 3 itens ao nosso menu sendo eles Home, Tarefas e Perfil e no final da implementação nosso XML menu ficará da seguinte forma:

Forma final do XML menu

Perceba que cada tag <item/> possui 3 atributos e cada um deles representa uma aspecto importante de cada item.

  1. id: O atributo id serve para identificar qual fragment aquele item se refere, faremos essa conexão mais tarde durante a configuração do Navigation Component.
  2. title: O atributo title serve para identificar qual o texto que irá junto com o ícone. Dentro do Bottom Navigation propriamente dito podemos configurar se o texto irá aparecer ou não, mas mesmo que o desenvolvedor opte por esconder os textos é importante que eles estejam presentes ao menos no XML menu que preenche a Bottom Navigation.
  3. icon: O atributo icon define qual o ícone correspondente aquele item. É interessante que o ícone tente se relacionar com o conteúdo de sua respectiva página na navegação.

Anexando o menu de itens ao Bottom Navigation

Agora com o menu devidamente configurado podemos retornar ao XML da Main Activity e definir que o nosso componente será preenchido pelo menu que acabamos de criar, para isso basta referenciar nosso menu na propriedade app:menu.

Caso queira que os títulos dos menus não apareçam é possível adicionar o atributo a baixo dentro do Bottom Navigation, mas para essa demonstração não faremos dessa forma.

app:labelVisibilityMode="unlabeled"

Depois de anexar o menu podemos ver no preview que nossos itens definidos no menu estão aparecendo corretamente e nesse estágio já podemos rodar a aplicação, porém ao trocar entre os itens nada irá acontecer porque ainda não configuramos a Bottom Navigation para interagir com as páginas, e o mais importante de tudo: Ainda nem criamos as páginas.

Aplicativo rodando após a inserção do menu.

Criando as telas da aplicação

Por questões didáticas as 3 telas dessa aplicação de demonstração serão compostas por 3 fragments sem comportamento algum, e o único elemento em tela será uma TextView com seu respectivo título para que se possível diferenciar uma tela da outra. Dessa forma teremos ao total 4 arquivos no nosso projeto: A Main Activity que irá hospedar a Bottom Navigation e as 3 fragments que representam uma tela cada uma.

Criando um Navigation Graph para a Bottom Navigation

A forma de implementação que usaremos nessa demonstração depende do Navigation Component do Android JetPack, uma biblioteca que visa facilitar a navegação dentro de um aplicativo Android, e a lógica por trás desse método está em conectar o fluxo de naveção do JetPack com a Bottom Navigation View de forma que o próprio Android consiga lidar com as mudanças na tela.

Para criar um Navigation Graph basta ir no subdiretório navigation dentro do diretório res ( Caso ele não exista no seu projeto o processo de criação é exatamente o mesmo do menu, só que ao invés do resource type ser menu escolha navigation) clicar com o botão direito e selecionar Create New Resource File, selecione o nome que você quiser e clique em ok.

Assim que clicar em ok caso não tenha a dependência do Navigation Component instalada no seu projeto uma janela de erro aparecerá notificando que criar um Navigation Graph só é possível com esse dependência instalada então é só clicar em Ok que o Android Studio irá instalar essa dependência automaticamente.

Adicionando Fragments a um Navigation Graph

Agora com o Navigation Graph criado iremos colocar as 3 páginas da nossa aplicação nesse gráfico, a forma mais prática de fazer esse processo é pela aba design do XML de navegação, clique no ícone indicado a baixa e selecione suas 3 fragments uma de cada vez.

Se tudo der certo o resultado será algo próximo a imagem abaixo, o board da Navigation Graph irá ser preenchido com previews das fragments selecionadas. Note que sempre uma das fragments possuirá um ícone de uma casinha na esquerda do título, isso serve para identificar qual será a página padrão quando a View que hosteia a navegação for carregada, você pode livremente alterar qual página é a principal clicando com o botão direito em alguma outra e selecionando a opção “Set as start destination

Depois de inserir as fragments no NavGraph troque para a aba code do XML e você verá que para cada fragment inserida no NavGraph irá ser gerada uma tag <fragment/> contendo algumas propriedades.

Agora faremos algumas pequenas alterações que farão toda a diferença, perceba que todas as tags fragment possuem uma propriedade chamada “id” o que precisaremos fazer é alterar o valor dessas propriedades de acordo com o que definimos no nosso menu XML.

Perceba que o atributo id de todas as fragments do NavGraph foram alterados para serem exatamente iguais aos seus respectivos itens no menu, dessa forma nós podemos conectar o menu com o NavGraph e fazer com que seja renderizada na tela a fragment correspondente ao item que for selecionado no menu.

Criando um container para a navegação

Para que as fragments sejam renderizadas na nossa activity nós precisaremos de um container aonde as páginas selecionadas na Bottom Navigation serão exibidas, então retornaremos ao XML da nossa Main Activity e faremos o seguinte processo:

  1. Alterar para a aba Design
  2. Na parte esquerda da tela escolher o item “Containers
  3. Procure pelo item chamado “NavHostFragment” e arraste-o para o canvas
  4. No menu que será aberto selecione o seu NavGraph para que o componente já seja gerado configurado da forma que desejamos.
  5. Redimensione o componente criado para que ele ocupe todo o espaço que você julgue necessário, geralmente quando estamos lidando com esse tipo de navegação o container costuma ocupar toda a tela exceto o espaço da bottom navigation view.

Após o processo descrito acima o XML da nossa Main Activity agora possui esse formato:

Perceba que esse componente já possui uma tag id padrão para que seja possível encontrá-la programaticamente, é recomendado que esse id seja trocado para um nome mais descritivo pro contexto da sua aplicação porém nesse exemplo iremos manter o id padrão.

O que define esse container como sendo o hospedeiro do nosso NavGraph é a propriedade “app:navGraph”, que define esse componente como sendo um local aonde as fragments conectadas ao Graph serão renderizadas.

Conectando a Bottom Navigation com o Navegador do container

Após todos esses passos parece que já está tudo pronto e nosso app já está implementado para navegar entre as fragments usando a Bottom Navigation como controlador.

Porém caso você decida rodar a aplicação agora perceberá que a página principal definida no NavGraph irá aparecer porém os botões não irão funcionar, isso acontece porque ainda não conectados o controlador de navegação do NavGraph com a nossa Bottom Navigation e para sso precisaremos ir até a Main Activity para configurar essa ligação.

Para isso iremos criar uma função chamada setUpBottomNavigation que será responsável por anexar o controlador de navegação do NavGraph ao nosso BottomNavigation.

E agora iremos chamar essa função no método OnCreate da nossa activity, logo após o método setContentView e então a estrutura final da nossa Main Activity será algo próximo a imagem abaixo:

Agora você poderá rodar a aplicação e navegar entre as fragments utilizando uma Bottom Navigation View como controladora do fluxo.

Por baixo dos panos

O que acontece por baixo dos panos quando fazemos uma navegação da forma que foi descrita nessa demonstração é que a Bottom Navigation View se conecta ao Navigation Graph e permite que seja possível fazer a transição de fragments de maneira quase automática.

Toda vez que o usuário troca de página usando a Bottom Navigation o ciclo de vida da fragment atual é encerrado com a chamada do método OnDestroy() e a nova fragment começa o seu ciclo de vida com a chamada do método OnCreateView(), e é assim que é feito o controle dsa fragments com essa implementação.

Conclusão

Existem n formas de implementar a mesma solução para um problema no mundo da programação, e essa implementação é somente uma entre várias outras formas.

A principal vantagem dessa abordagem é a velocidade que é possível criar uma navegação amigável para o usuário sem ter que se aprofundar muito no funcionamento interno do Kotlin ou do Android.

Entretanto devido ao fato do controle das fragments ser feito de forma que uma é destruída sempre que trocamos para outra página essa implementação pode não ser ideal para grandes projetos que se baseiam em consultas a API’s ou que possuem processamento pesado dentro das páginas, mas sim para aplicativos menores em que a complexidade das telas não seja tão alta.

--

--

Lucca Beurmann
Lucca Beurmann

Written by Lucca Beurmann

Mobile Software Developer, technology enthusiast, video game lover and a cat person.

No responses yet