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());
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,
// FlatButton 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.
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.
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: () => {},
),
],
),
),
);
- 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),
]
)
);
}
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
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
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 ❤
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: RaisedButton(
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: RaisedButton(
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: RaisedButton(
onPressed: () {
Get.back();
},
child: Text('Voltar!'),
),
),
);
}
}
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:
- Dynamic Themes in 3 lines using Get - Tutorial by Rod Brown.
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
)
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: FlatButton(
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")
),
),
),
);
}
}
),