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.

  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.
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(),);
  }
}
default

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

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;
default
  • _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.

    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'),
          )
        ],
      ),
    );
default

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.

printscreen of home tab
Figure 1: printscreen of home tab
printscreen of drawer
Figure 2: printscreen of drawer
animated demo of app
Figure 3: animated demo of app

Coloquei este demo no meu github.

Espero ter ajudado.