Skip to content

Latest commit

 

History

History
558 lines (455 loc) · 15 KB

route_management.md

File metadata and controls

558 lines (455 loc) · 15 KB

Navegação sem rotas nomeadas

Para navegar para uma próxima tela:

Get.to(ProximaTela());

Para fechar snackbars, dialogs, bottomsheets, ou qualquer coisa que você normalmente fecharia com o Navigator.pop(context) (como por exemplo fechar a View atual e voltar para a anterior):

Get.back();

Para ir para a próxima tela e NÃO deixar opção para voltar para a tela anterior (bom para SplashScreens, telas de login e etc.):

Get.off(ProximaTela());

Para ir para a próxima tela e cancelar todas as rotas anteriores (útil em telas de carrinho, votações ou testes):

Get.offAll(ProximaTela());

Para navegar para a próxima rota, e receber ou atualizar dados assim que retornar da rota:

var dados = await Get.to(Pagamento());

Na outra tela, envie os dados para a rota anterior:

Get.back(result: 'sucesso');

E use-os:

if (dados == 'sucesso') fazerQualquerCoisa();

Não quer aprender nossa sintaxe? Apenas mude o Navigator (letra maiúscula) para navigator (letra minúscula), e você terá todas as funcionalidades de navegação padrão, sem precisar usar context

Exemplo:

// Navigator padrão do Flutter
Navigator.of(context).push(
  context,
  MaterialPageRoute(
    builder: (BuildContext context) {
      return HomePage();
    },
  ),
);

// Get usando a sintaxe Flutter sem precisar do context
navigator.push(
  MaterialPageRoute(
      builder: (_) {
      return HomePage();
    },
  ),
);

// Sintaxe do Get (é bem melhor, mas você tem o direito de discordar)
Get.to(HomePage());

SnackBars

Para ter um SnackBar simples no Flutter, você precisa do context do Scaffold, ou uma GlobalKey atrelada ao seu Scaffold.

final snackBar = SnackBar(
  content: Text('Olá!'),
  action: SnackBarAction(
    label: 'Eu sou uma SnackBar velha e feia :(',
    onPressed: (){}
  ),
);
// Encontra o Scaffold na árvore de Widgets e
// o usa para mostrar o SnackBar
Scaffold.of(context).showSnackBar(snackBar);

Com o Get:

Get.snackbar('Olá', 'eu sou uma SnackBar moderna e linda!');

Com Get, tudo que você precisa fazer é chamar Get.snackbar() de qualquer lugar no seu código, e/ou customizá-lo da forma que quiser!

Get.snackbar(
  "Ei, eu sou uma SnackBar Get!", // título
  "É inacreditável! Eu estou usando uma SnackBar sem context, sem boilerplate, sem Scaffold!", // mensagem
  icon: Icon(Icons.alarm),
  shouldIconPulse: true,
  onTap:(){},
  barBlur: 20,
  isDismissible: true,
  duration: Duration(seconds: 3),
);


  ////////// TODOS OS RECURSOS //////////
  //     Color colorText,
  //     Duration duration,
  //     SnackPosition snackPosition,
  //     Widget titleText,
  //     Widget messageText,
  //     bool instantInit,
  //     Widget icon,
  //     bool shouldIconPulse,
  //     double maxWidth,
  //     EdgeInsets margin,
  //     EdgeInsets padding,
  //     double borderRadius,
  //     Color borderColor,
  //     double borderWidth,
  //     Color backgroundColor,
  //     Color leftBarIndicatorColor,
  //     List<BoxShadow> boxShadows,
  //     Gradient backgroundGradient,
  //     TextButton mainButton,
  //     OnTap onTap,
  //     bool isDismissible,
  //     bool showProgressIndicator,
  //     AnimationController progressIndicatorController,
  //     Color progressIndicatorBackgroundColor,
  //     Animation<Color> progressIndicatorValueColor,
  //     SnackStyle snackStyle,
  //     Curve forwardAnimationCurve,
  //     Curve reverseAnimationCurve,
  //     Duration animationDuration,
  //     double barBlur,
  //     double overlayBlur,
  //     Color overlayColor,
  //     Form userInputForm
  ///////////////////////////////////

Se você prefere a SnackBar tradicional, ou quer customizar por completo, como por exemplo fazer ele ter uma só linha (Get.snackbar tem os parâmetros title e message obrigatórios), você pode usar Get.rawSnackbar(); que fornece a API bruta na qual Get.snackbar foi contruído.

Dialogs

Para abrir um dialog:

Get.dialog(SeuWidgetDialog());

Para abrir um dialog padrão:

Get.defaultDialog(
  onConfirm: () => print("Ok"),
  middleText: "Dialog made in 3 lines of code",
);

Você também pode usar Get.generalDialog em vez de showGeneralDialog.

Para todos os outros Widgets do tipo dialog do Flutter, incluindo os do Cupertino, você pode usar Get.overlayContext em vez do context, e abrir em qualquer lugar do seu código.

Para widgets que não usam overlayContext, você pode usar Get.context. Esses dois contextos vão funcionar em 99% dos casos para substituir o context da sua UI, exceto em casos onde o inheritedWidget é usado sem a navigation context.

BottomSheets

Get.bottomSheet() é tipo o showModalBottomSheet(), mas não precisa do context.

Get.bottomSheet(
  Container(
    child: Wrap(
      children: <Widget>[
        ListTile(
          leading: Icon(Icons.music_note),
          title: Text('Música'),
          onTap: () {}
        ),
        ListTile(
          leading: Icon(Icons.videocam),
          title: Text('Vídeo'),
          onTap: () {},
        ),
      ],
    ),
  ),
);

Navegar com rotas nomeadas

  • Se você prefere navegar por rotas nomeadas, Get também dá suporte a isso:

Para navegar para uma nova tela

Get.toNamed("/ProximaTela");

Para navegar para uma tela sem a opção de voltar para a rota atual.

Get.offNamed("/ProximaTela");

Para navegar para uma nova tela e remover todas rotas anteriores da stack

Get.offAllNamed("/ProximaTela");

Para definir rotas, use o GetMaterialApp:

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => Home()),
        GetPage(name: '/login', page: () => Login()),
        GetPage(name: '/cadastro', page: () => Cadastro(), transition: Transition.cupertino),
      ]
    )
  );
}

Para lidar com a navegação para rotas não definidas (erro 404), você pode definir uma página unknownRoute em GetMaterialApp.

void main() {
  runApp(
    GetMaterialApp(
      unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => Second()),
      ],
    )
  );
}

Enviar dados para rotas nomeadas

Apenas envie o que você quiser no parâmetro arguments. Get aceita qualquer coisa aqui, seja String, Map, List, ou até a instância de uma classe.

Get.toNamed("/ProximaTela", arguments: 'Get é o melhor');

Na sua classe ou controller:

print(Get.arguments); //valor: Get é o melhor

Links de Url dinâmicos

Get oferece links de url dinâmicos assim como na Web. Desenvolvedores Web provavelmente já queriam essa feature no Flutter, e muito provavelmente viram um package que promete essa feature mas entrega uma sintaxe totalmente diferente do que uma url teria na web, mas o Get também resolve isso.

Get.offAllNamed("/ProximaTela?device=phone&id=354&name=Enzo");

na sua classe controller/bloc/stateful/stateless:

print(Get.parameters['id']); // valor: 354
print(Get.parameters['name']); // valor: Enzo

Você também pode receber parâmetros nomeados com o Get facilmente:

void main() => runApp(
  GetMaterialApp(
    initialRoute: '/',
    getPages: [
      GetPage(name: '/', page: () => Home()),
      /// Importante! ':user' não é uma nova rota, é somente uma
      /// especificação do parâmentro. Não use '/segunda/:user/' e '/segunda'
      /// se você precisa de uma nova rota para o user, então
      /// use '/segunda/user/:user' se '/segunda' for uma rota
      GetPage(name: '/segunda/:user', page: () => Segunda()), // recebe a ID
      GetPage(name: '/terceira', page: () => Terceira(), transition: Transition.cupertino),
    ]
  ),
);

Envie dados na rota nomeada

Get.toNamed("/segunda/34954");

Na segunda tela receba os dados usando Get.parameters[]

print(Get.parameters['user']);
// valor: 34954

ou envie vários parâmetros como este

Get.toNamed("/profile/34954?flag=true");

Na segunda tela, pegue os dados por parâmetros normalmente

print(Get.parameters['user']);
print(Get.parameters['flag']);
// valor: 34954 true

E agora, tudo que você precisa fazer é usar Get.toNamed) para navegar por suas rotas nomeadas, sem nenhum context (você pode chamar suas rotas diretamente do seu BLoc ou do Controller), e quando seu aplicativo é compilado para a web, suas rotas vão aparecer na url ❤

Middleware

Se você quer escutar eventos do Get para ativar ações, você pode usar routingCallback para isso

GetMaterialApp(
  routingCallback: (route){
    if(routing.current == '/segunda'){
      openAds();
    }
  }
)

Se você não estiver usando o GetMaterialApp, você pode usar a API manual para anexar um observer Middleware.

void main() {
  runApp(
    MaterialApp(
      onGenerateRoute: Router.generateRoute,
      initialRoute: "/",
      navigatorKey: Get.key,
      navigatorObservers: [
        GetObserver(MiddleWare.observer), // AQUI !!!
      ],
    )
  );
}

Criar uma classe MiddleWare

class MiddleWare {
  static observer(Routing routing) {
    /// Você pode escutar junto com as rotas, snackbars, dialogs
    /// e bottomsheets em cada tela.
    /// Se você precisar entrar em algum um desses 3 eventos aqui diretamente,
    /// você precisa especificar que o evento é != do que você está tentando fazer
    if (routing.current == '/segunda' && !routing.isSnackbar) {
      Get.snackbar("Olá", "Você está na segunda rota");
    } else if (routing.current =='/terceira'){
      print('última rota chamada');
    }
  }
}

Agora, use Get no seu código:

class Primeira extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            Get.snackbar("Oi", "eu sou uma snackbar moderna");
          },
        ),
        title: Text('Primeira rota'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Abrir rota'),
          onPressed: () {
            Get.toNamed("/segunda");
          },
        ),
      ),
    );
  }
}

class Segunda extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            Get.snackbar("Oi", "eu sou uma snackbar moderna");
          },
        ),
        title: Text('Segunda rota'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Abrir rota'),
          onPressed: () {
            Get.toNamed("/terceira");
          },
        ),
      ),
    );
  }
}

class Terceira extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Terceira Rota"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Get.back();
          },
          child: Text('Voltar!'),
        ),
      ),
    );
  }
}

Change Theme

Por favor não use nenhum widget acima do GetMaterialApp para atualizá-lo. Isso pode ativar keys duplicadas. Muitas pessoas estão acostumadas com a forma pré-história de criar um widget ThemeProvider só pra mudar o tema do seu app, e isso definitamente NÃO é necessário com o Get.

Você pode criar seu tema customizado e simplesmente adicionar ele dentro de Get.changeTheme() sem nenhum boilerplate para isso:

Get.changeTheme(ThemeData.light());

Se você quer criar algo como um botão que muda o tema com um toque, você pode combinar duas APIs do Get para isso, a API que checa se o tema dark está sendo usado, e a API de mudança de tema. E dentro de um onPressed você coloca isso:

Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());

Quando o modo escuro está ativado, ele vai alterar para o modo claro, e vice versa.

Se você quer saber a fundo como mudar o tema, você pode seguir esse tutorial no Medium que até te ensina a persistir o tema usando Get e shared_preferences:

Configurações Globais Opcionais

Você pode mudar configurações globais para o Get. Apenas adicione Get.config no seu código antes de ir para qualquer rota ou faça diretamente no seu GetMaterialApp

// essa forma
GetMaterialApp(
  enableLog: true,
  defaultTransition: Transition.fade,
  opaqueRoute: Get.isOpaqueRouteDefault,
  popGesture: Get.isPopGestureEnable,
  transitionDuration: Get.defaultDurationTransition,
  defaultGlobalState: Get.defaultGlobalState,
);

// ou essa
Get.config(
  enableLog = true,
  defaultPopGesture = true,
  defaultTransition = Transitions.cupertino
)

Nested Navigators

Get fez a navegação aninhada no Flutter mais fácil ainda. Você não precisa do context, e você encontrará sua navigation stack pela ID.

  • Nota: Criar navegação paralela em stacks pode ser perigoso. O idela é não usar NestedNavigators, ou usar com moderação. Se o seu projeto requer isso, vá em frente, mas fique ciente que manter múltiplas stacks de navegação na memória pode não ser uma boa ideia no quesito consumo de RAM.

Veja como é simples:

Navigator(
  key: nestedKey(1), // crie uma key com um index
  initialRoute: '/',
  onGenerateRoute: (settings) {
    if (settings.name == '/') {
      return GetPageRoute(
        page: () => Scaffold(
          appBar: AppBar(
            title: Text("Principal"),
          ),
          body: Center(
            child: TextButton(
              color: Colors.blue,
              child: Text("Ir para a segunda"),
              onPressed: () {
                Get.toNamed('/segunda', id:1); // navega pela sua navegação aninhada usando o index
              },
            )
          ),
        ),
      );
    } else if (settings.name == '/segunda') {
      return GetPageRoute(
        page: () => Center(
          child: Scaffold(
            appBar: AppBar(
              title: Text("Principal"),
            ),
            body: Center(
              child:  Text("Segunda")
            ),
          ),
        ),
      );
    }
  }
),