Flutter tornou-se um kit de ferramentas popular para a construção de aplicativos de plataforma cruzada. Suporta todas as principais plataformas, incluindo Android, iOS e a web.
A navegação é muito importante para qualquer aplicativo. Ele fornece uma abstração uniforme sobre APIs de navegação fornecidas por várias plataformas. O Flutter fornece dois tipos de APIs para navegação: imperativa e declarativa.
Neste tutorial, vamos cobrir a abordagem imperativa para navegação usada no Flutter 1.0, bem como a abordagem declarativa agora empregada no Flutter 2.0.
Veremos o seguinte:
Navegação imperativa (Flutter 1.0) Classe Flutter Navigator Rotas nomeadas Navegação declarativa ( Flutter 2.0) Flutter Navigator Usando RouterDelegate RouteInformationParser Juntando tudo
Navegação imperativa (Flutter 1.0)
O Flutter 1.0 adotou uma abordagem imperativa para a navegação .
No Flut Além disso, a navegação consiste em uma pilha de widgets em que os widgets são colocados na parte superior e exibidos na parte superior também.
Classe Flutter Navigator
O classe Navigator fornece todos os recursos de navegação em um aplicativo Flutter.
O Navigator fornece métodos para modifique a pilha empurrando para empilhar ou removendo-a da pilha. O método Navigator.push é para navegar para uma página mais recente e Navigator.pop é para voltar da página atual.
Aqui está um exemplo básico de pop e push: o método push leva BuildContext como o primeiro argumento e o segundo argumento é um PageBuilder. Este exemplo usa MaterialPageRoute, que fornece a animação de transição e lida com alterações de rota:
import’package: flutter/material.dart’; void main () {runApp (MaterialApp (title:’My App’, home: Main (),)); } class Main extends StatelessWidget {@override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (title: Text (‘Main Route’),), body: Center (child: RaisedButton (child: Text (‘Open route’), onPressed: () {//empurrando SecondRoute Navigator.push (context, MaterialPageRoute (builder: (context)=> SecondRoute ()),);},),),); }}
O método pop usa apenas BuildContext e altera a rota atual.
class SecondRoute extends StatelessWidget {@override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (title: Text (“Second Route”),), body: Center (child: RaisedButton (onPressed: () {//Removendo SecondRoute Navigator.pop (context);}, child: Text (‘Go back!’),),),); }}
O Navigator fornece mais métodos, incluindo * pushReplacement *, que tornam os argumentos semelhantes a push. Ele substituirá a rota atual, portanto, não é possível navegar de volta para a rota mais antiga.
Por exemplo, após o login bem-sucedido, você deseja usar * pushReplacement * para evitar que o usuário retorne à tela de login.
Rotas nomeadas
As rotas nomeadas permitem que você altere o caminho usando strings em vez de fornecer classes de componentes, o que, por sua vez, permite reutilizar o código.
Rotas nomeadas são definidas como um mapa no MaterialApp. Essas rotas podem ser usadas em qualquer parte do aplicativo.
Definindo rotas
A rota é um mapa com chaves de string e valores como construtores que são passados para a propriedade routes em MaterialApp:
void main () {runApp (MaterialApp (title:’My App’, home: Main (),//Rotas definidas aqui rotas: {“second”:( context)=> SecondRoute ()},)) ; }
Usando rotas nomeadas
Em vez de push, pushNamed é usado para mudar para uma nova rota. Da mesma forma, * pushReplacementNamed * é usado em vez de pushReplacement. O método pop é o mesmo para todas as rotas.
class Main extends StatelessWidget {@override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (title: Text (‘Main Route’),), body: Center (child: RaisedButton (child: Text (‘Open route’), onPressed: () {Navigator.pushReplacementNamed (context,”second”);},),),); }}
Navegação declarativa (Flutter 2.0)
O Flutter 2.0 vem com navegação renovada graças em grande parte ao seu suporte para um abordagem declarativa . Isso torna o roteamento uma função de estado-ou seja, as páginas mudam após a mudança de estado.
O Flutter 2.0 também tem um suporte melhor para navegação na web .
Este diagrama, compartilhado publicamente pela equipe do Flutter para anunciar Flutter Navigation 2.0 e Router , descreve o fluxo muito bem:
Flutter Navigator
O Navigator pega uma lista de páginas e exibe a última página. Você pode alterar suas páginas adicionando ou removendo páginas do final da lista.
O exemplo abaixo demonstra como usar a classe Navigator com o novo Flutter Navigator usando a navegação baseada em páginas.
O _page é gerenciado por estado por esta classe. Para navegação, esta _page é manipulada na chamada setState:
class _App extends State {//Criando estado para páginas List
A _page é passada para a classe Navigator. O Navigator mudará a página atual com base no valor de _page.
onPopPage é chamado quando a navegação baseada no sistema operacional é realizada, como pressionar o botão Voltar no Android, etc.
@override Widget build (Contexto BuildContext) {return MaterialApp (home: Navigator (onPopPage: (rota, resultado) {//verificar se a rota foi removida se (route.didPop (resultado)) {//remover a última página _pages.removeLast (); retornar verdadeiro ;} retornar falso;}, páginas: _pages,),); }}
A página inicial pode ser definida adicionando uma página no método de ciclo de vida initState:
@override void initState () {super.initState ();//configuração da página inicial _pages=[_ buildMain ()]; }
Para criar uma nova página de material, use o widget MaterialPage. MaterialPage leva um filho e uma chave. O Navigator usa a chave para diferenciar as páginas e detectar a alteração da página.
Ao clicar no botão, uma nova página é adicionada ao estado _page. setState é chamado para acionar uma reconstrução do widget e o Navigator lida automaticamente com a mudança de página.
//Esta função cria uma página usando MaterialPage Page _buildMain () {return MaterialPage (child: Scaffold (body: Center (child: ElevatedButton) (child: Text (“click”), onPressed: () {//Quando clicado, adiciona uma nova página a _page list _pages.add (_buildSecondPage ());//chama setState para acionar a reconstrução do widget setState (() {//criar uma cópia do array _pages=_pages.toList ();});},),),//Isso ajuda o Navigator a distinguir entre páginas diferentes), chave: ValueKey (“home”)); }
Esta página é construída da mesma forma que _buildMain, mas em vez de adicionar uma nova página, ele remove uma e inicia a reconstrução.
//Esta função executa a mesma tarefa que _buildMain Página _buildSecondPage () {return MaterialPage (child: Scaffold (body: Center (child: ElevatedButton (child: Text (“back”), onPressed: () {//Isso levará de volta ao main//remover a última página _pages.removeLast ();//chamar setState para acionar uma reconstrução setState (() {//criando uma cópia da lista _pages=_pages.toList ();});},),),), chave: ValueKey (“segundo”)); }
Além de usar a lista _pages como um estado, você pode usar qualquer outro estado para realizar a navegação. Aqui está outro exemplo:
class _App extends State {String _selected=”main”; Page _buildMain () {return MaterialPage (child: Scaffold (appBar: AppBar (), body: Center (child: ElevatedButton (child: Text (“click”), onPressed: () {setState (() {//adicionar um novo página _selected=”segundo”;});},),),), chave: ValueKey (“home”)); } Page _buildSecondPage () {return MaterialPage (child: Scaffold (appBar: AppBar (), body: Center (child: ElevatedButton (child: Text (“back”), onPressed: () {setState (() {//mudar de volta estado para principal _selected=”principal”;});},),),), chave: ValueKey (“segundo”)); } @override Widget build (BuildContext context) {return MaterialApp (home: Navigator (onPopPage: (route, result) {if (route.didPop (result)) {_selected=”main”; return true;} return false;}, páginas: [_buildMain (),//mostra apenas selecionar se o estado tiver o segundo selecionado if (_selected==”segundo”) _buildSecondPage ()],),); }}
Usando RouterDelegate
RouterDelegate é um widget central usado pelo Roteador. Ele responde à intenção do motor de push de rota e pop de rota. A nova navegação permite a criação de RouterDelegate para melhor controle da navegação.
Um RouterDelegate é criado estendendo a classe RouterDelegate
_selecionado rastreia a rota atual. Isso é semelhante ao estado usado no exemplo anterior.
a classe AppRouter estende RouterDelegate
Isso é usado pelo roteador para obter o estado mais recente do roteador e alterar a URL na barra de endereço.
//obter o estado correto do roteador @override AppRouteState get currentConfiguration=> AppRouteState (_selected);
A tecla de navegação é usada para oferecer suporte à navegação mais antiga.
//Isso para suporte à navegação mais antiga. final _navigation=GlobalKey
NoticeListeners é usado em vez de setState para acionar uma reconstrução. _selected é alterado para alterar a rota.
Page _buildMain () {return MaterialPage (child: Scaffold (appBar: AppBar (), body: Center (child: ElevatedButton (child: Text (“click”), onPressed: ( ) {_selected=”second”;//notificar mudanças de rota notificarListeners ();},),),), chave: ValueKey (“home”)); }
Isso é semelhante a _buildMain:
Page _buildSecondPage () {return MaterialPage (child: Scaffold (appBar: AppBar (), body: Center (child: ElevatedButton (child: Text (“back”), onPressed: () {_selected=”main”;//notificar mudanças de rota notificarListeners ();},),),), chave: ValueKey (“segundo”)); }
A função build retorna o widget Navigator, que é usado para criar o layout de outras páginas. Esta função é semelhante à construção da função anterior. Em vez de setState, notificaListeners é usado para acionar a reconstrução.
@override Widget build (BuildContext context) {return MaterialApp (home: Navigator (key: _navigation, onPopPage: (route, result) {if (! Route.didPop ( resultado)) {return false;} _selected=”main”;//notificar mudanças de rota notificarListeners (); return true;}, pages: [_buildMain (),//se a rota é a segunda mostra SecondPage if (_selected==”second”) _buildSecondPage ()],),); }
Esta função usa informações passadas pelo roteador para alterar a rota. Esta função é chamada para alterar a rota quando o mecanismo passa a intenção de push ou pop de rota. As informações passadas aqui são analisadas por uma classe diferente que discutiremos mais tarde.
@override Future
RouteInformationParser
setNewRoutePath recebe a configuração do roteador. Esta configuração é analisada por RouteInformationParser.
Para o estado de análise passado pelo sistema operacional, mecanismo, etc., uma classe deve estender RouteInformationParser. restoreRouteInformation obtém o valor de retorno de currentConfiguration e o converte em RouteInformation.
parseRouteInformation retorna o estado do roteador, que é passado para setNewRoutePath.
class AppRouteInformationParser extends RouteInformationParser
Juntando tudo
MaterialApp agora tem um construtor recém-nomeado, que implementa um roteador que recebe Delegate e InformationParser como argumentos.
class _App extends State {@override Widget build ( Contexto BuildContext) {return MaterialApp.router (routeInformationParser: AppRouteInformationParser (), routerDelegate: AppRouter ()); }}
Conclusão
Neste tutorial de navegação Flutter, explicamos como implementar a navegação em um aplicativo Flutter de acordo com a abordagem imperativa usada no Flutter 1.0 e a nova navegação declarativa introduzida com o Flutter 2.0.
Dependendo da natureza do seu projeto Flutter, qualquer tipo de navegação pode ser apropriado, mas também não é uma bala de lasca. Você deve sempre escolher a abordagem que melhor atende às suas necessidades, mesmo que isso signifique empregar uma combinação de ambas.
Para começar a navegar no Flutter, recomendo conferir Fluro e pacotes Voyager .