- [Navegação sem rotas nomeadas](#navegação-sem-rotas-nomeadas)
  - [SnackBars](#snackbars)
  - [Dialogs](#dialogs)
  - [BottomSheets](#bottomsheets)
- [Navegar com rotas nomeadas](#navegar-com-rotas-nomeadas)
  - [Enviar dados para rotas nomeadas](#enviar-dados-para-rotas-nomeadas)
    - [Links de Url dinâmicos](#links-de-url-dinâmicos)
    - [Middleware](#middleware)
  - [Change Theme](#change-theme)
  - [Configurações Globais Opcionais](#configurações-globais-opcionais)
  - [Nested Navigators](#nested-navigators)

## Navegação sem rotas nomeadas

Para navegar para uma próxima tela:

```dart
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):

```dart
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.):

```dart
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):

```dart
Get.offAll(ProximaTela());
```

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

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

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

```dart
Get.back(result: 'sucesso');
```

E use-os:

```dart
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:

```dart
// 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.

```dart
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:

```dart
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!

```dart
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:

```dart
Get.dialog(SeuWidgetDialog());
```

Para abrir um dialog padrão:

```dart
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.

```dart
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

```dart
Get.toNamed("/ProximaTela");
```

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

```dart
Get.offNamed("/ProximaTela");
```

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

```dart
Get.offAllNamed("/ProximaTela");
```

Para definir rotas, use o `GetMaterialApp`:

```dart
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.

```dart
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.

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

Na sua classe ou controller:

```dart
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.

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

na sua classe controller/bloc/stateful/stateless:

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

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

```dart
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

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

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

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


ou envie vários parâmetros como este

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

Na segunda tela, pegue os dados por parâmetros normalmente
```dart
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

```dart
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.

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

Criar uma classe MiddleWare

```dart
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:

```dart
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:

```dart
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:

```dart
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:

- [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr).

### 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

```dart
// 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:
```dart
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")
            ),
          ),
        ),
      );
    }
  }
),
```
