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
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
Coloquei este demo no meu github.
Espero ter ajudado.