Navegação por abas no final da tela (BottomNavigationBar). (#dev #flutter, #dart)

Navegação por abas no final da tela (BottomNavigationBar). (#dev #flutter, #dart)

Overview

Se você é um desenvolvedor Flutter procurando maneiras de melhorar a navegação no seu app, veio ao lugar certo! Neste post, compartilho uma forma simples mas poderosa de usar o BottomNavigationBar para organizar a navegação por abas, bem como incorporar um menu lateral para enriquecer a experiência do usuário. Tudo isso sem o uso de pacotes externos. Acompanhe para ver como você pode implementar esta solução no seu projeto!

Demonstração de como utilizar o widget BottomNavigationBar para criar navegação por abas localizadas no final da tela. Aproveitei e inclui neste demo uma forma de navegar pelas abas utilizando o menu lateral.

Neste demo não foi utilizado nenhum pacote que não seja o nativo.

Do que esta demonstração é composta?

  1. APP_TITLE: Constante com o título da aplicação;
  2. SamplePageWidget: Widget contendo um ícone e um texto logo abaixo. Estes dois itens sao passados no construtor, então uso este mesmo widget para simular paginas diferentes.
  3. CustomAppDrawer: Menu lateral com links para as paginas.
  4. BottomNavigationWidget: Onde está toda a lógica de utilização das abas.

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bottom_tab_demo/consts.dart';
import 'package:flutter_bottom_tab_demo/widgets/bottom_navigation_widget.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: APP_TITLE,
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: BottomNavigationWidget(),);
  }
}

O arquivo principal não tem nada em especial. Mudei o titulo e home widget.

bottom_navigation_widget.dart

Este arquivo possui 3 propriedades:

  int _currentTab = 0;
  List<Widget> _tabs = [
    SamplePageWidget(Icons.home, 'This is the home of your app!'),
    SamplePageWidget(Icons.camera, 'Imagine your camera working here...'),
    SamplePageWidget(Icons.photo_library, 'Photos would be placed here.'),
  ];
  bool loadedOnceFromRoute = false;
  • _currentTab guarda o índice da aba atual;
  • _tabs guarda a lista com todas as tabs que podem ser carregadas. A ordem dos itens aqui é importante.
  • loadedOnceFromRoute não faz parte do controle via abas.

Outro ponto importante deste widget: ele é statefull.

dentro do método build

    return Scaffold(
      appBar: AppBar(title: Text(APP_TITLE)),
      drawer: CustomAppDrawer(),
      body: _tabs[_currentTab],
      
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentTab,
        onTap: (indexOfClickedTab) {
          setState(() {
            _currentTab = indexOfClickedTab;
          });
        },        
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.camera),
            title: Text('Camera'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.photo_library),
            title: Text('Gallery'),
          )
        ],
      ),
    );

Dentro do Scaffold:

  • appBar: Um app bar comum;
  • drawer: o menu lateral que utilizo no app
  • body: o widget que será exibido é o que está na variável _tabs, na posição definida na variável _currentTab.
  • bottomNavigationBar: Aqui começa o controle de navegação por abas.
    • currentIndex: este é o índice da aba que está selecionada. deve corresponder a algumas das posições dentro da propriedade _tabs.
    • onTap: callback que recebe o índice da tab selecionada e executa algum código. No caso, estou chamando o método setState e atualizo o valor da variável _currentTab com o da que foi selecionada.
    • items: lista de itens que serão exibidos. estas são as abas. Cada aba é um widget do tipo BottomNavigationBarItem que recebe um ícone e um titulo. Vale lembrar que esta lista e a lista que existe na variável _tabs devem estar na mesma ordem.

Resumindo, o controle de navegação por abas é a coordenação entre duas listas: a que possui os widgets de paginas e a que possui as abas (BottomNavigationBarItem). Quando você clica em uma das abas, é executada um função que recebe o índice (atenção: índice == posição da aba no vetor de abas (BottomNavigationBarItem)). O próximo passo é mudar o widget que está sendo exibdo na tela. isso é feito com a chamada para a função setState.

Prints

printscreen of home tab

printscreen of home tab

printscreen of drawer

printscreen of drawer

animated demo of app

animated demo of app

Coloquei este demo no meu github.

Espero ter ajudado.