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?
- APP_TITLE: Constante com o título da aplicação;
- 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.
- CustomAppDrawer: Menu lateral com links para as paginas.
- BottomNavigationWidget: Onde está toda a lógica de utilização das abas.
main.dart
1import 'package:flutter/material.dart';
2import 'package:flutter_bottom_tab_demo/consts.dart';
3import 'package:flutter_bottom_tab_demo/widgets/bottom_navigation_widget.dart';
4
5void main() {
6 runApp(MyApp());
7}
8
9class MyApp extends StatelessWidget {
10 @override
11 Widget build(BuildContext context) {
12 return MaterialApp(
13 title: APP_TITLE,
14 theme: ThemeData(
15 primarySwatch: Colors.blue,
16 visualDensity: VisualDensity.adaptivePlatformDensity,
17 ),
18 home: BottomNavigationWidget(),);
19 }
20}
O arquivo principal não tem nada em especial. Mudei o titulo e home widget.
bottom_navigation_widget.dart
Este arquivo possui 3 propriedades:
1 int _currentTab = 0;
2 List<Widget> _tabs = [
3 SamplePageWidget(Icons.home, 'This is the home of your app!'),
4 SamplePageWidget(Icons.camera, 'Imagine your camera working here...'),
5 SamplePageWidget(Icons.photo_library, 'Photos would be placed here.'),
6 ];
7 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
1 return Scaffold(
2 appBar: AppBar(title: Text(APP_TITLE)),
3 drawer: CustomAppDrawer(),
4 body: _tabs[_currentTab],
5
6 bottomNavigationBar: BottomNavigationBar(
7 currentIndex: _currentTab,
8 onTap: (indexOfClickedTab) {
9 setState(() {
10 _currentTab = indexOfClickedTab;
11 });
12 },
13 items: [
14 BottomNavigationBarItem(
15 icon: Icon(Icons.home),
16 title: Text('Home'),
17 ),
18 BottomNavigationBarItem(
19 icon: Icon(Icons.camera),
20 title: Text('Camera'),
21 ),
22 BottomNavigationBarItem(
23 icon: Icon(Icons.photo_library),
24 title: Text('Gallery'),
25 )
26 ],
27 ),
28 );
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 drawer

animated demo of app
Coloquei este demo no meu github.
Espero ter ajudado.