Showing
7 changed files
with
383 additions
and
94 deletions
@@ -189,3 +189,15 @@ | @@ -189,3 +189,15 @@ | ||
189 | - Added overlayContext | 189 | - Added overlayContext |
190 | - Fix Duration transition | 190 | - Fix Duration transition |
191 | 191 | ||
192 | +## [1.16.1-dev] | ||
193 | +- Improve: GetObserver | ||
194 | + | ||
195 | +## [1.17.0-dev] | ||
196 | +- Added experimental APIs | ||
197 | + | ||
198 | +## [1.18.0-dev] | ||
199 | +- Added SafeArea to bottomsheets | ||
200 | +- Added docs | ||
201 | + | ||
202 | +## [1.19.0-dev] | ||
203 | +- Added nested navigators |
@@ -4,14 +4,26 @@ A consistent navigation library that lets you navigate between screens, open dia | @@ -4,14 +4,26 @@ A consistent navigation library that lets you navigate between screens, open dia | ||
4 | ## Getting Started | 4 | ## Getting Started |
5 | 5 | ||
6 | Flutter's conventional navigation has a lot of unnecessary boilerplate, requires context to navigate between screens, open dialogs, and use snackbars on framework is really painful. | 6 | Flutter's conventional navigation has a lot of unnecessary boilerplate, requires context to navigate between screens, open dialogs, and use snackbars on framework is really painful. |
7 | -In addition, with each route navigation, all of your screens below MaterialApp are rebuilt, often causing RAM and CPU bottlenecks. | ||
8 | -I worked on a pull to fix it in the framework, and seeing how things work I realized that a lot of cliche code could be avoided to get clean and concise code. | ||
9 | -With that in mind, I created this library that will change the way you work with the Framework and save your life from cliche code, | ||
10 | -increasing your productivity, and eliminating all the bugs present in Flutter's default navigation altogether. | 7 | +In addition, when a route is pushed, the entire MaterialApp can be rebuilt causing freezes, this does not happen with Get. |
8 | +This library that will change the way you work with the Framework and save your life from cliche code, increasing your productivity, and eliminating the rebuild bugs of your application. | ||
11 | 9 | ||
12 | -##### If you use MODULAR, add on your MaterialApp this: navigatorKey: Get.addKey(Modular.navigatorKey) | 10 | +```dart |
11 | +// Default Flutter navigator | ||
12 | +Navigator.push( | ||
13 | + context, | ||
14 | + MaterialPageRoute( | ||
15 | + builder: (context) { | ||
16 | + return Home(); | ||
17 | + }, | ||
18 | + ), | ||
19 | + ); | ||
20 | + | ||
21 | +// Get sintax | ||
22 | +Get.to(Home()); | ||
23 | +``` | ||
13 | 24 | ||
14 | -##### If you use master/dev branch of Flutter, use the version 1.16.0-dev. | 25 | +##### If you use master/dev/beta branch of Flutter, use the version 1.19.0-dev. |
26 | +* If you use MODULAR, add on your MaterialApp this: navigatorKey: Get.addKey(Modular.navigatorKey) | ||
15 | 27 | ||
16 | ## How to use? | 28 | ## How to use? |
17 | 29 | ||
@@ -19,7 +31,7 @@ Add this to your package's pubspec.yaml file: | @@ -19,7 +31,7 @@ Add this to your package's pubspec.yaml file: | ||
19 | 31 | ||
20 | ``` | 32 | ``` |
21 | dependencies: | 33 | dependencies: |
22 | - get: ^1.12.0 // ^1.16.0-dev on dev/master | 34 | + get: ^1.15.2 // ^1.19.0-dev on dev/master |
23 | ``` | 35 | ``` |
24 | 36 | ||
25 | And import it: | 37 | And import it: |
@@ -74,14 +86,56 @@ ex: | @@ -74,14 +86,56 @@ ex: | ||
74 | if(data == 'sucess') madeAnything(); | 86 | if(data == 'sucess') madeAnything(); |
75 | ``` | 87 | ``` |
76 | 88 | ||
89 | +Don't you want to learn our syntax? | ||
90 | +Just change the Navigator (uppercase) to navigator (lowercase), and you will have all the functions of the standard browser, without having to use context | ||
91 | +Example: | ||
92 | + | ||
93 | +```dart | ||
94 | +// Default Flutter navigator | ||
95 | +Navigator.push( | ||
96 | + context, | ||
97 | + MaterialPageRoute( | ||
98 | + builder: (context) { | ||
99 | + return HomePage(); | ||
100 | + }, | ||
101 | + ), | ||
102 | + ); | ||
103 | + | ||
104 | +// Get with no context but Flutter sintax | ||
105 | +navigator.push( | ||
106 | + MaterialPageRoute( | ||
107 | + builder: (context) { | ||
108 | + return HomePage(); | ||
109 | + }, | ||
110 | + ), | ||
111 | + ); | ||
112 | + | ||
113 | +// Get sintax (Much better, but we respect your opinion) | ||
114 | +Get.to(HomePage()); | ||
115 | +``` | ||
77 | 116 | ||
78 | ### SnackBars | 117 | ### SnackBars |
79 | -To show a modern snackbar: | 118 | + |
119 | +To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, | ||
120 | +```dart | ||
121 | +final snackBar = SnackBar( | ||
122 | + content: Text('Hi!'), | ||
123 | + action: SnackBarAction( | ||
124 | + label: 'I am a old and ugly snackbar :(', | ||
125 | + onPressed: (){} | ||
126 | + ), | ||
127 | + // Find the Scaffold in the widget tree and use | ||
128 | + // it to show a SnackBar. | ||
129 | + Scaffold.of(context).showSnackBar(snackBar); | ||
130 | +``` | ||
131 | + | ||
132 | +With Get: | ||
133 | + | ||
80 | ```dart | 134 | ```dart |
81 | Get.snackbar('Hi', 'i am a modern snackbar'); | 135 | Get.snackbar('Hi', 'i am a modern snackbar'); |
82 | ``` | 136 | ``` |
83 | -To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, | ||
84 | -but with Get, all you have to do is call your Get.snackbar from anywhere in your code or customize it however you want! | 137 | + |
138 | +With Get, all you have to do is call your Get.snackbar from anywhere in your code or customize it however you want! | ||
85 | 139 | ||
86 | ```dart | 140 | ```dart |
87 | Get.snackbar( | 141 | Get.snackbar( |
@@ -131,7 +185,8 @@ but with Get, all you have to do is call your Get.snackbar from anywhere in your | @@ -131,7 +185,8 @@ but with Get, all you have to do is call your Get.snackbar from anywhere in your | ||
131 | // Form userInputForm | 185 | // Form userInputForm |
132 | /////////////////////////////////// | 186 | /////////////////////////////////// |
133 | ``` | 187 | ``` |
134 | -If you prefer the traditional snackbar, or want to customize it from scratch, including adding just one line (Get.snackbar makes use of a mandatory title and message), you can use GetBar (). Show () which provides the RAW API on which Get.snackbar was built. | 188 | +If you prefer the traditional snackbar, or want to customize it from scratch, including adding just one line (Get.snackbar makes use of a mandatory title and message), you can use |
189 | +`GetBar().show();` which provides the RAW API on which Get.snackbar was built. | ||
135 | 190 | ||
136 | ### Dialogs | 191 | ### Dialogs |
137 | 192 | ||
@@ -192,6 +247,7 @@ Get.config( | @@ -192,6 +247,7 @@ Get.config( | ||
192 | defaultTransition = Transitions.cupertino} | 247 | defaultTransition = Transitions.cupertino} |
193 | ``` | 248 | ``` |
194 | 249 | ||
250 | + | ||
195 | ## Navigate with named routes: | 251 | ## Navigate with named routes: |
196 | - Yes, and with no navigation bug, add "named" to Get. HOWEVER, TO MAKE THIS TYPE OF NAVIGATION, USE THE ROUTE MODEL FROM REPOSITORY. | 252 | - Yes, and with no navigation bug, add "named" to Get. HOWEVER, TO MAKE THIS TYPE OF NAVIGATION, USE THE ROUTE MODEL FROM REPOSITORY. |
197 | Example of navigation with named routes: | 253 | Example of navigation with named routes: |
@@ -290,7 +346,7 @@ class Router { | @@ -290,7 +346,7 @@ class Router { | ||
290 | } | 346 | } |
291 | ``` | 347 | ``` |
292 | 348 | ||
293 | -And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (BLoC will love it), and when your app is compiled to the web, your routes will appear in the url beautifully <3 | 349 | +And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url beautifully <3 |
294 | 350 | ||
295 | ```dart | 351 | ```dart |
296 | class First extends StatelessWidget { | 352 | class First extends StatelessWidget { |
@@ -363,6 +419,94 @@ class Third extends StatelessWidget { | @@ -363,6 +419,94 @@ class Third extends StatelessWidget { | ||
363 | } | 419 | } |
364 | ``` | 420 | ``` |
365 | 421 | ||
422 | + | ||
423 | +### Advanced APIs | ||
424 | +Each day Get gets further away from the standard Framework, and provides a wider range of features that are unthinkable to be executed using the standard Flutter. | ||
425 | +With Get 1.17.0 a range of new APIs was launched, which allow access from arguments of a named route to whether there is a snackbar or dialog open at that moment, or which screen is being displayed. | ||
426 | +This is a big step towards completely detaching the Flutter navigation from InheritedWidgets. Using context to access an InheritedWidget to access a simple navigation feature is one of the only boring things to do in this incredible framework, and now Get has solved this problem, it has become omniscient, and you will have access to basically any tool Flutter which is only available within the widget tree using it. | ||
427 | + | ||
428 | +All APIs available here are in beta stage, so if you find any errors here, open an issue or offer a PR. | ||
429 | + | ||
430 | +```dart | ||
431 | +MaterialApp( | ||
432 | + navigatorKey: Get.key, | ||
433 | + navigatorObservers: [GetObserver()], // ADD THIS !!!! | ||
434 | + ); | ||
435 | +``` | ||
436 | + | ||
437 | +You will also be able to use your own Middleware within GetObserver, this will not influence anything. | ||
438 | + | ||
439 | +```dart | ||
440 | +MaterialApp( | ||
441 | + navigatorKey: Get.key, | ||
442 | + navigatorObservers: [GetObserver(MiddleWare.observer)], // Here | ||
443 | + ); | ||
444 | +``` | ||
445 | + | ||
446 | +```dart | ||
447 | +Get.arguments // give the current args from currentScreen | ||
448 | + | ||
449 | +Get.previousArguments // give arguments of previous route | ||
450 | + | ||
451 | +Get.previousRoute // give name of previous route | ||
452 | + | ||
453 | +Get.rawRoute // give the raw route to access for example, rawRoute.isFirst() | ||
454 | + | ||
455 | +Get.routing // give access to Rounting API from GetObserver | ||
456 | + | ||
457 | +Get.isSnackbarOpen // check if snackbar is open | ||
458 | + | ||
459 | +Get.isDialogOpen // check if dialog is open | ||
460 | + | ||
461 | +Get.isBottomSheetOpen // check if bottomsheet is open | ||
462 | + | ||
463 | + | ||
464 | +``` | ||
465 | +### Nested Navigators | ||
466 | + | ||
467 | +Get made Flutter's nested navigation even easier. | ||
468 | +You don't need the context, and you will find your navigation stack by Id. | ||
469 | + | ||
470 | +See how simple it is: | ||
471 | +```dart | ||
472 | + Navigator( | ||
473 | + key: nestedKey(1), // create a key by index | ||
474 | + initialRoute: '/', | ||
475 | + onGenerateRoute: (settings) { | ||
476 | + if (settings.name == '/') { | ||
477 | + return GetRoute( | ||
478 | + page: Scaffold( | ||
479 | + appBar: AppBar( | ||
480 | + title: Text("Main"), | ||
481 | + ), | ||
482 | + body: Center( | ||
483 | + child: FlatButton( | ||
484 | + color: Colors.blue, | ||
485 | + onPressed: () { | ||
486 | + Get.toNamed('/second', 1); // navigate by your nested route by index | ||
487 | + }, | ||
488 | + child: Text("Go to second")), | ||
489 | + ), | ||
490 | + ), | ||
491 | + ); | ||
492 | + } else if (settings.name == '/second') { | ||
493 | + return GetRoute( | ||
494 | + page: Center( | ||
495 | + child: Scaffold( | ||
496 | + appBar: AppBar( | ||
497 | + title: Text("Main"), | ||
498 | + ), | ||
499 | + body: Center( | ||
500 | + child: Text("second") | ||
501 | + ), | ||
502 | + ), | ||
503 | + ), | ||
504 | + ); | ||
505 | + } | ||
506 | + }), | ||
507 | +``` | ||
508 | + | ||
509 | + | ||
366 | ### Others methods (docs will be added soon): | 510 | ### Others methods (docs will be added soon): |
367 | 511 | ||
368 | ```dart | 512 | ```dart |
@@ -380,6 +524,7 @@ Get.height / Get.width // Equivalent to the method: MediaQuery.of(context).size. | @@ -380,6 +524,7 @@ Get.height / Get.width // Equivalent to the method: MediaQuery.of(context).size. | ||
380 | 524 | ||
381 | Get.context // Gives the context of the screen in the foreground anywhere in your code. | 525 | Get.context // Gives the context of the screen in the foreground anywhere in your code. |
382 | 526 | ||
527 | +@deprecated on 1.17.0 | ||
383 | var arguments = Get.args(context); // Gives current route arguments | 528 | var arguments = Get.args(context); // Gives current route arguments |
384 | ``` | 529 | ``` |
385 | 530 |
@@ -8,6 +8,10 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | @@ -8,6 +8,10 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
8 | this.backgroundColor, | 8 | this.backgroundColor, |
9 | this.elevation, | 9 | this.elevation, |
10 | this.shape, | 10 | this.shape, |
11 | + this.removeBottom = false, | ||
12 | + this.removeLeft = false, | ||
13 | + this.removeRight = false, | ||
14 | + this.removeTop = true, | ||
11 | this.clipBehavior, | 15 | this.clipBehavior, |
12 | this.modalBarrierColor, | 16 | this.modalBarrierColor, |
13 | this.isDismissible = true, | 17 | this.isDismissible = true, |
@@ -30,6 +34,15 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | @@ -30,6 +34,15 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
30 | final bool isDismissible; | 34 | final bool isDismissible; |
31 | final bool enableDrag; | 35 | final bool enableDrag; |
32 | 36 | ||
37 | + // remove safearea from top | ||
38 | + final bool removeTop; | ||
39 | + // remove safearea from bottom | ||
40 | + final bool removeBottom; | ||
41 | + // remove safearea from left | ||
42 | + final bool removeLeft; | ||
43 | + // remove safearea from right | ||
44 | + final bool removeRight; | ||
45 | + | ||
33 | @override | 46 | @override |
34 | Duration get transitionDuration => Duration(milliseconds: 700); | 47 | Duration get transitionDuration => Duration(milliseconds: 700); |
35 | 48 | ||
@@ -61,7 +74,10 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | @@ -61,7 +74,10 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
61 | // and isn't exposed to the top padding of the MediaQuery. | 74 | // and isn't exposed to the top padding of the MediaQuery. |
62 | Widget bottomSheet = MediaQuery.removePadding( | 75 | Widget bottomSheet = MediaQuery.removePadding( |
63 | context: context, | 76 | context: context, |
64 | - removeTop: true, | 77 | + removeTop: removeTop, |
78 | + removeBottom: removeBottom, | ||
79 | + removeLeft: removeLeft, | ||
80 | + removeRight: removeRight, | ||
65 | child: _GetModalBottomSheet<T>( | 81 | child: _GetModalBottomSheet<T>( |
66 | route: this, | 82 | route: this, |
67 | backgroundColor: backgroundColor ?? | 83 | backgroundColor: backgroundColor ?? |
@@ -56,74 +56,121 @@ class Get { | @@ -56,74 +56,121 @@ class Get { | ||
56 | {bool opaque, | 56 | {bool opaque, |
57 | Transition transition, | 57 | Transition transition, |
58 | Duration duration, | 58 | Duration duration, |
59 | + int id, | ||
59 | bool popGesture}) { | 60 | bool popGesture}) { |
60 | - // if (key.currentState.mounted) // add this if appear problems on future with route navigate | ||
61 | - // when widget don't mounted | 61 | + if (id == null) { |
62 | return key.currentState.push(GetRoute( | 62 | return key.currentState.push(GetRoute( |
63 | opaque: opaque ?? true, | 63 | opaque: opaque ?? true, |
64 | page: page, | 64 | page: page, |
65 | popGesture: popGesture ?? _defaultPopGesture, | 65 | popGesture: popGesture ?? _defaultPopGesture, |
66 | transition: transition ?? _defaultTransition, | 66 | transition: transition ?? _defaultTransition, |
67 | transitionDuration: duration ?? const Duration(milliseconds: 400))); | 67 | transitionDuration: duration ?? const Duration(milliseconds: 400))); |
68 | + } else { | ||
69 | + return global(id).currentState.push(GetRoute( | ||
70 | + opaque: opaque ?? true, | ||
71 | + page: page, | ||
72 | + popGesture: popGesture ?? _defaultPopGesture, | ||
73 | + transition: transition ?? _defaultTransition, | ||
74 | + transitionDuration: duration ?? const Duration(milliseconds: 400))); | ||
75 | + } | ||
68 | } | 76 | } |
69 | 77 | ||
70 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed | 78 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed |
71 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior | 79 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior |
72 | /// of rebuilding every app after a route, use opaque = true as the parameter. | 80 | /// of rebuilding every app after a route, use opaque = true as the parameter. |
73 | - static Future<T> toNamed<T>(String page, {arguments}) { | 81 | + static Future<T> toNamed<T>(String page, {arguments, int id}) { |
74 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 82 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
75 | // when widget don't mounted | 83 | // when widget don't mounted |
84 | + if (id == null) { | ||
76 | return key.currentState.pushNamed(page, arguments: arguments); | 85 | return key.currentState.pushNamed(page, arguments: arguments); |
86 | + } else { | ||
87 | + return global(id).currentState.pushNamed(page, arguments: arguments); | ||
88 | + } | ||
77 | } | 89 | } |
78 | 90 | ||
79 | /// It replaces Navigator.pushReplacementNamed, but needs no context. | 91 | /// It replaces Navigator.pushReplacementNamed, but needs no context. |
80 | - static Future<T> offNamed<T>(String page, {arguments}) { | 92 | + static Future<T> offNamed<T>(String page, {arguments, int id}) { |
81 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 93 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
82 | // when widget don't mounted | 94 | // when widget don't mounted |
95 | + if (id == null) { | ||
83 | return key.currentState.pushReplacementNamed(page, arguments: arguments); | 96 | return key.currentState.pushReplacementNamed(page, arguments: arguments); |
97 | + } else { | ||
98 | + return global(id) | ||
99 | + .currentState | ||
100 | + .pushReplacementNamed(page, arguments: arguments); | ||
101 | + } | ||
84 | } | 102 | } |
85 | 103 | ||
86 | /// It replaces Navigator.popUntil, but needs no context. | 104 | /// It replaces Navigator.popUntil, but needs no context. |
87 | - static void until(String page, predicate) { | 105 | + static void until(String page, predicate, {int id}) { |
88 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 106 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
89 | // when widget don't mounted | 107 | // when widget don't mounted |
108 | + if (id == null) { | ||
90 | return key.currentState.popUntil(predicate); | 109 | return key.currentState.popUntil(predicate); |
110 | + } else { | ||
111 | + return global(id).currentState.popUntil(predicate); | ||
112 | + } | ||
91 | } | 113 | } |
92 | 114 | ||
93 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context. | 115 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context. |
94 | - static Future<T> offUntil<T>(page, predicate) { | 116 | + static Future<T> offUntil<T>(page, predicate, {int id}) { |
95 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 117 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
96 | // when widget don't mounted | 118 | // when widget don't mounted |
119 | + if (id == null) { | ||
97 | return key.currentState.pushAndRemoveUntil(page, predicate); | 120 | return key.currentState.pushAndRemoveUntil(page, predicate); |
121 | + } else { | ||
122 | + return global(id).currentState.pushAndRemoveUntil(page, predicate); | ||
123 | + } | ||
98 | } | 124 | } |
99 | 125 | ||
100 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. | 126 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. |
101 | - static Future<T> offNamedUntil<T>(page, predicate) { | 127 | + static Future<T> offNamedUntil<T>(page, predicate, {int id}) { |
102 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 128 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
103 | // when widget don't mounted | 129 | // when widget don't mounted |
130 | + if (id == null) { | ||
104 | return key.currentState.pushNamedAndRemoveUntil(page, predicate); | 131 | return key.currentState.pushNamedAndRemoveUntil(page, predicate); |
132 | + } else { | ||
133 | + return global(id).currentState.pushNamedAndRemoveUntil(page, predicate); | ||
134 | + } | ||
105 | } | 135 | } |
106 | 136 | ||
107 | /// It replaces Navigator.removeRoute, but needs no context. | 137 | /// It replaces Navigator.removeRoute, but needs no context. |
108 | - static void removeRoute(route) { | 138 | + static void removeRoute(route, {int id}) { |
139 | + if (id == null) { | ||
109 | return key.currentState.removeRoute(route); | 140 | return key.currentState.removeRoute(route); |
141 | + } else { | ||
142 | + return global(id).currentState.removeRoute(route); | ||
143 | + } | ||
110 | } | 144 | } |
111 | 145 | ||
112 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. | 146 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. |
113 | - static Future<T> offAllNamed<T>( | ||
114 | - String newRouteName, { | ||
115 | - RoutePredicate predicate, | ||
116 | - arguments, | ||
117 | - }) { | 147 | + static Future<T> offAllNamed<T>(String newRouteName, |
148 | + {RoutePredicate predicate, arguments, int id}) { | ||
118 | var route = (Route<dynamic> rota) => false; | 149 | var route = (Route<dynamic> rota) => false; |
150 | + | ||
151 | + if (id == null) { | ||
119 | return key.currentState.pushNamedAndRemoveUntil( | 152 | return key.currentState.pushNamedAndRemoveUntil( |
120 | newRouteName, predicate ?? route, | 153 | newRouteName, predicate ?? route, |
121 | arguments: arguments); | 154 | arguments: arguments); |
155 | + } else { | ||
156 | + return global(id).currentState.pushNamedAndRemoveUntil( | ||
157 | + newRouteName, predicate ?? route, | ||
158 | + arguments: arguments); | ||
159 | + } | ||
122 | } | 160 | } |
123 | 161 | ||
124 | /// It replaces Navigator.pop, but needs no context. | 162 | /// It replaces Navigator.pop, but needs no context. |
125 | - static back({dynamic result}) { | ||
126 | - return key.currentState.pop(result); | 163 | + static void back({dynamic result, int id}) { |
164 | + if (id == null) { | ||
165 | + key.currentState.pop(result); | ||
166 | + } else { | ||
167 | + global(id).currentState.pop(result); | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + /// Experimental API to back from overlay | ||
172 | + static void backE({dynamic result}) { | ||
173 | + Navigator.pop(overlayContext); | ||
127 | } | 174 | } |
128 | 175 | ||
129 | /// It will close as many screens as you define. Times must be> 0; | 176 | /// It will close as many screens as you define. Times must be> 0; |
@@ -145,13 +192,23 @@ class Get { | @@ -145,13 +192,23 @@ class Get { | ||
145 | {bool opaque = false, | 192 | {bool opaque = false, |
146 | Transition transition, | 193 | Transition transition, |
147 | bool popGesture, | 194 | bool popGesture, |
195 | + int id, | ||
148 | Duration duration = const Duration(milliseconds: 400)}) { | 196 | Duration duration = const Duration(milliseconds: 400)}) { |
197 | + if (id == null) { | ||
149 | return key.currentState.pushReplacement(GetRoute( | 198 | return key.currentState.pushReplacement(GetRoute( |
150 | opaque: opaque ?? true, | 199 | opaque: opaque ?? true, |
151 | page: page, | 200 | page: page, |
152 | popGesture: popGesture ?? _defaultPopGesture, | 201 | popGesture: popGesture ?? _defaultPopGesture, |
153 | transition: transition ?? _defaultTransition, | 202 | transition: transition ?? _defaultTransition, |
154 | transitionDuration: duration)); | 203 | transitionDuration: duration)); |
204 | + } else { | ||
205 | + return global(id).currentState.pushReplacement(GetRoute( | ||
206 | + opaque: opaque ?? true, | ||
207 | + page: page, | ||
208 | + popGesture: popGesture ?? _defaultPopGesture, | ||
209 | + transition: transition ?? _defaultTransition, | ||
210 | + transitionDuration: duration)); | ||
211 | + } | ||
155 | } | 212 | } |
156 | 213 | ||
157 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context | 214 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context |
@@ -159,8 +216,11 @@ class Get { | @@ -159,8 +216,11 @@ class Get { | ||
159 | {RoutePredicate predicate, | 216 | {RoutePredicate predicate, |
160 | bool opaque = false, | 217 | bool opaque = false, |
161 | bool popGesture, | 218 | bool popGesture, |
219 | + int id, | ||
162 | Transition transition}) { | 220 | Transition transition}) { |
163 | var route = (Route<dynamic> rota) => false; | 221 | var route = (Route<dynamic> rota) => false; |
222 | + | ||
223 | + if (id == null) { | ||
164 | return key.currentState.pushAndRemoveUntil( | 224 | return key.currentState.pushAndRemoveUntil( |
165 | GetRoute( | 225 | GetRoute( |
166 | opaque: opaque ?? true, | 226 | opaque: opaque ?? true, |
@@ -169,6 +229,16 @@ class Get { | @@ -169,6 +229,16 @@ class Get { | ||
169 | transition: transition ?? _defaultTransition, | 229 | transition: transition ?? _defaultTransition, |
170 | ), | 230 | ), |
171 | predicate ?? route); | 231 | predicate ?? route); |
232 | + } else { | ||
233 | + return global(id).currentState.pushAndRemoveUntil( | ||
234 | + GetRoute( | ||
235 | + opaque: opaque ?? true, | ||
236 | + popGesture: popGesture ?? _defaultPopGesture, | ||
237 | + page: page, | ||
238 | + transition: transition ?? _defaultTransition, | ||
239 | + ), | ||
240 | + predicate ?? route); | ||
241 | + } | ||
172 | } | 242 | } |
173 | 243 | ||
174 | /// Show a dialog. You can choose color and opacity of background | 244 | /// Show a dialog. You can choose color and opacity of background |
@@ -205,7 +275,7 @@ class Get { | @@ -205,7 +275,7 @@ class Get { | ||
205 | ); | 275 | ); |
206 | } | 276 | } |
207 | 277 | ||
208 | - static defaultDialog( | 278 | + static Future<T> defaultDialog<T>( |
209 | {Color color, | 279 | {Color color, |
210 | double opacity = 0.2, | 280 | double opacity = 0.2, |
211 | String title = "Alert dialog", | 281 | String title = "Alert dialog", |
@@ -221,7 +291,7 @@ class Get { | @@ -221,7 +291,7 @@ class Get { | ||
221 | confirm: confirm, | 291 | confirm: confirm, |
222 | ); | 292 | ); |
223 | 293 | ||
224 | - dialog(child); | 294 | + return dialog(child); |
225 | } | 295 | } |
226 | 296 | ||
227 | static Future<T> bottomSheet<T>({ | 297 | static Future<T> bottomSheet<T>({ |
@@ -231,6 +301,7 @@ class Get { | @@ -231,6 +301,7 @@ class Get { | ||
231 | ShapeBorder shape, | 301 | ShapeBorder shape, |
232 | Clip clipBehavior, | 302 | Clip clipBehavior, |
233 | Color barrierColor, | 303 | Color barrierColor, |
304 | + bool ignoreSafeArea, | ||
234 | bool isScrollControlled = false, | 305 | bool isScrollControlled = false, |
235 | bool useRootNavigator = false, | 306 | bool useRootNavigator = false, |
236 | bool isDismissible = true, | 307 | bool isDismissible = true, |
@@ -248,9 +319,10 @@ class Get { | @@ -248,9 +319,10 @@ class Get { | ||
248 | isScrollControlled: isScrollControlled, | 319 | isScrollControlled: isScrollControlled, |
249 | barrierLabel: MaterialLocalizations.of(Get.key.currentContext) | 320 | barrierLabel: MaterialLocalizations.of(Get.key.currentContext) |
250 | .modalBarrierDismissLabel, | 321 | .modalBarrierDismissLabel, |
251 | - backgroundColor: backgroundColor, | 322 | + backgroundColor: backgroundColor ?? Colors.transparent, |
252 | elevation: elevation, | 323 | elevation: elevation, |
253 | shape: shape, | 324 | shape: shape, |
325 | + removeTop: ignoreSafeArea ?? true, | ||
254 | clipBehavior: clipBehavior, | 326 | clipBehavior: clipBehavior, |
255 | isDismissible: isDismissible, | 327 | isDismissible: isDismissible, |
256 | modalBarrierColor: barrierColor, | 328 | modalBarrierColor: barrierColor, |
@@ -259,10 +331,11 @@ class Get { | @@ -259,10 +331,11 @@ class Get { | ||
259 | )); | 331 | )); |
260 | } | 332 | } |
261 | 333 | ||
262 | - /// get arguments from current screen. You need of context | ||
263 | - static args(context) { | ||
264 | - return ModalRoute.of(context).settings.arguments; | ||
265 | - } | 334 | + // /// get arguments from current screen. You need of context |
335 | + // @deprecated | ||
336 | + // static args(context) { | ||
337 | + // return ModalRoute.of(context).settings.arguments; | ||
338 | + // } | ||
266 | 339 | ||
267 | static Future backdrop(Widget child, | 340 | static Future backdrop(Widget child, |
268 | {double radius = 20.0, | 341 | {double radius = 20.0, |
@@ -395,18 +468,75 @@ class Get { | @@ -395,18 +468,75 @@ class Get { | ||
395 | } | 468 | } |
396 | } | 469 | } |
397 | 470 | ||
471 | + static Map<int, GlobalKey<NavigatorState>> _keys = {}; | ||
472 | + | ||
473 | + static GlobalKey<NavigatorState> nestedKey(int key) { | ||
474 | + _keys.putIfAbsent(key, () => GlobalKey<NavigatorState>()); | ||
475 | + return _keys[key]; | ||
476 | + } | ||
477 | + | ||
478 | + static GlobalKey<NavigatorState> global(int key) { | ||
479 | + if (!_keys.containsKey(key)) { | ||
480 | + throw 'route id not found'; | ||
481 | + } | ||
482 | + final recoverKey = _keys[key]; | ||
483 | + return recoverKey; | ||
484 | + } | ||
485 | + | ||
486 | + /// give access to Routing API from GetObserver | ||
487 | + static Routing get routing => _routing; | ||
488 | + | ||
489 | + static Routing _routing; | ||
490 | + | ||
491 | + static setRouting(Routing rt) { | ||
492 | + _routing = rt; | ||
493 | + } | ||
494 | + | ||
495 | + /// give current arguments | ||
496 | + static get arguments => _routing.args; | ||
497 | + | ||
498 | + /// give arguments from previous route | ||
499 | + static get previousArguments => _routing.previousArgs; | ||
500 | + | ||
501 | + /// give name from current route | ||
502 | + static get currentRoute => _routing.current; | ||
503 | + | ||
504 | + /// give name from previous route | ||
505 | + static get previousRoute => _routing.previous; | ||
506 | + | ||
507 | + /// check if snackbar is open | ||
508 | + static bool get isSnackbarOpen => _routing.isSnackbar; | ||
509 | + | ||
510 | + /// check if dialog is open | ||
511 | + static bool get isDialogOpen => _routing.isDialog; | ||
512 | + | ||
513 | + /// check if bottomsheet is open | ||
514 | + static bool get isBottomSheetOpen => _routing.isBottomSheet; | ||
515 | + | ||
516 | + /// check a raw current route | ||
517 | + static Route<dynamic> get rawRoute => _routing.route; | ||
518 | + | ||
519 | + /// check if log is enable | ||
398 | static bool get isLogEnable => _enableLog; | 520 | static bool get isLogEnable => _enableLog; |
521 | + | ||
522 | + /// check if popGesture is enable | ||
399 | static bool get isPopGestureEnable => _defaultPopGesture; | 523 | static bool get isPopGestureEnable => _defaultPopGesture; |
524 | + | ||
525 | + /// check if default opaque route is enable | ||
400 | static bool get isOpaqueRouteDefault => _defaultOpaqueRoute; | 526 | static bool get isOpaqueRouteDefault => _defaultOpaqueRoute; |
401 | 527 | ||
402 | /// give access to currentContext | 528 | /// give access to currentContext |
403 | static BuildContext get context => key.currentContext; | 529 | static BuildContext get context => key.currentContext; |
404 | 530 | ||
531 | + /// give access to current Overlay Context | ||
405 | static BuildContext get overlayContext => key.currentState.overlay.context; | 532 | static BuildContext get overlayContext => key.currentState.overlay.context; |
406 | 533 | ||
407 | /// give access to Theme.of(context) | 534 | /// give access to Theme.of(context) |
408 | static ThemeData get theme => Theme.of(context); | 535 | static ThemeData get theme => Theme.of(context); |
409 | 536 | ||
537 | + /// give access to Mediaquery.of(context) | ||
538 | + static MediaQueryData get mediaquery => MediaQuery.of(context); | ||
539 | + | ||
410 | /// give access to Theme.of(context).iconTheme.color | 540 | /// give access to Theme.of(context).iconTheme.color |
411 | static Color get iconColor => Theme.of(context).iconTheme.color; | 541 | static Color get iconColor => Theme.of(context).iconTheme.color; |
412 | 542 |
@@ -8,6 +8,7 @@ class Routing { | @@ -8,6 +8,7 @@ class Routing { | ||
8 | final args; | 8 | final args; |
9 | final previousArgs; | 9 | final previousArgs; |
10 | final removed; | 10 | final removed; |
11 | + final Route<dynamic> route; | ||
11 | final bool isBack; | 12 | final bool isBack; |
12 | final bool isSnackbar; | 13 | final bool isSnackbar; |
13 | final bool isBottomSheet; | 14 | final bool isBottomSheet; |
@@ -18,6 +19,7 @@ class Routing { | @@ -18,6 +19,7 @@ class Routing { | ||
18 | this.args, | 19 | this.args, |
19 | this.previousArgs, | 20 | this.previousArgs, |
20 | this.removed, | 21 | this.removed, |
22 | + this.route, | ||
21 | this.isBack, | 23 | this.isBack, |
22 | this.isSnackbar, | 24 | this.isSnackbar, |
23 | this.isBottomSheet, | 25 | this.isBottomSheet, |
@@ -27,7 +29,7 @@ class Routing { | @@ -27,7 +29,7 @@ class Routing { | ||
27 | 29 | ||
28 | class GetObserver extends NavigatorObserver { | 30 | class GetObserver extends NavigatorObserver { |
29 | final Function(Routing) routing; | 31 | final Function(Routing) routing; |
30 | - GetObserver(this.routing); | 32 | + GetObserver([this.routing]); |
31 | @override | 33 | @override |
32 | void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { | 34 | void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { |
33 | if ('${route?.settings?.name}' == 'snackbar') { | 35 | if ('${route?.settings?.name}' == 'snackbar') { |
@@ -40,14 +42,22 @@ class GetObserver extends NavigatorObserver { | @@ -40,14 +42,22 @@ class GetObserver extends NavigatorObserver { | ||
40 | if (Get.isLogEnable) print("[GOING TO ROUTE] ${route?.settings?.name}"); | 42 | if (Get.isLogEnable) print("[GOING TO ROUTE] ${route?.settings?.name}"); |
41 | } | 43 | } |
42 | 44 | ||
43 | - routing(Routing( | 45 | + final routeSend = Routing( |
44 | removed: null, | 46 | removed: null, |
45 | isBack: false, | 47 | isBack: false, |
48 | + route: route, | ||
46 | current: '${route?.settings?.name}', | 49 | current: '${route?.settings?.name}', |
47 | previous: '${previousRoute?.settings?.name}', | 50 | previous: '${previousRoute?.settings?.name}', |
48 | args: route?.settings?.arguments, | 51 | args: route?.settings?.arguments, |
49 | previousArgs: previousRoute?.settings?.arguments, | 52 | previousArgs: previousRoute?.settings?.arguments, |
50 | - isSnackbar: '${route?.settings?.name}' == 'snackbar')); | 53 | + isSnackbar: '${route?.settings?.name}' == 'snackbar', |
54 | + isDialog: '${route?.settings?.name}' == 'dialog', | ||
55 | + isBottomSheet: '${route?.settings?.name}' == 'bottomsheet', | ||
56 | + ); | ||
57 | + if (routing != null) { | ||
58 | + routing(routeSend); | ||
59 | + } | ||
60 | + Get.setRouting(routeSend); | ||
51 | } | 61 | } |
52 | 62 | ||
53 | @override | 63 | @override |
@@ -67,14 +77,23 @@ class GetObserver extends NavigatorObserver { | @@ -67,14 +77,23 @@ class GetObserver extends NavigatorObserver { | ||
67 | if (Get.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}"); | 77 | if (Get.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}"); |
68 | } | 78 | } |
69 | 79 | ||
70 | - routing(Routing( | 80 | + final routeSend = Routing( |
71 | removed: null, | 81 | removed: null, |
72 | isBack: true, | 82 | isBack: true, |
83 | + route: previousRoute, | ||
73 | current: '${previousRoute?.settings?.name}', | 84 | current: '${previousRoute?.settings?.name}', |
74 | previous: '${route?.settings?.name}', | 85 | previous: '${route?.settings?.name}', |
75 | args: previousRoute?.settings?.arguments, | 86 | args: previousRoute?.settings?.arguments, |
76 | previousArgs: route?.settings?.arguments, | 87 | previousArgs: route?.settings?.arguments, |
77 | - isSnackbar: '${route?.settings?.name}' == 'snackbar')); | 88 | + isSnackbar: false, //'${route?.settings?.name}' == 'snackbar', |
89 | + isDialog: false, //'${route?.settings?.name}' == 'dialog', | ||
90 | + isBottomSheet: false, //'${route?.settings?.name}' == 'bottomsheet', | ||
91 | + ); | ||
92 | + | ||
93 | + if (routing != null) { | ||
94 | + routing(routeSend); | ||
95 | + } | ||
96 | + Get.setRouting(routeSend); | ||
78 | } | 97 | } |
79 | 98 | ||
80 | @override | 99 | @override |
@@ -82,14 +101,22 @@ class GetObserver extends NavigatorObserver { | @@ -82,14 +101,22 @@ class GetObserver extends NavigatorObserver { | ||
82 | super.didReplace(newRoute: newRoute, oldRoute: oldRoute); | 101 | super.didReplace(newRoute: newRoute, oldRoute: oldRoute); |
83 | if (Get.isLogEnable) print("[REPLACE ROUTE] ${oldRoute?.settings?.name}"); | 102 | if (Get.isLogEnable) print("[REPLACE ROUTE] ${oldRoute?.settings?.name}"); |
84 | 103 | ||
85 | - routing(Routing( | 104 | + final routeSend = Routing( |
86 | removed: null, // add '${oldRoute?.settings?.name}' or remain null ??? | 105 | removed: null, // add '${oldRoute?.settings?.name}' or remain null ??? |
87 | isBack: false, | 106 | isBack: false, |
107 | + route: newRoute, | ||
88 | current: '${newRoute?.settings?.name}', | 108 | current: '${newRoute?.settings?.name}', |
89 | previous: '${oldRoute?.settings?.name}', | 109 | previous: '${oldRoute?.settings?.name}', |
90 | args: newRoute?.settings?.arguments, | 110 | args: newRoute?.settings?.arguments, |
91 | isSnackbar: null, | 111 | isSnackbar: null, |
92 | - previousArgs: null)); | 112 | + isBottomSheet: null, |
113 | + isDialog: null, | ||
114 | + previousArgs: null); | ||
115 | + | ||
116 | + if (routing != null) { | ||
117 | + routing(routeSend); | ||
118 | + } | ||
119 | + Get.setRouting(routeSend); | ||
93 | } | 120 | } |
94 | 121 | ||
95 | @override | 122 | @override |
@@ -97,13 +124,21 @@ class GetObserver extends NavigatorObserver { | @@ -97,13 +124,21 @@ class GetObserver extends NavigatorObserver { | ||
97 | super.didRemove(route, previousRoute); | 124 | super.didRemove(route, previousRoute); |
98 | if (Get.isLogEnable) print("[REMOVING ROUTE] ${route?.settings?.name}"); | 125 | if (Get.isLogEnable) print("[REMOVING ROUTE] ${route?.settings?.name}"); |
99 | 126 | ||
100 | - routing(Routing( | 127 | + final routeSend = Routing( |
101 | isBack: false, | 128 | isBack: false, |
129 | + route: previousRoute, | ||
102 | current: '${previousRoute?.settings?.name}', | 130 | current: '${previousRoute?.settings?.name}', |
103 | removed: '${route?.settings?.name}', | 131 | removed: '${route?.settings?.name}', |
104 | previous: null, | 132 | previous: null, |
105 | isSnackbar: null, | 133 | isSnackbar: null, |
134 | + isBottomSheet: null, | ||
135 | + isDialog: null, | ||
106 | args: previousRoute?.settings?.arguments, | 136 | args: previousRoute?.settings?.arguments, |
107 | - previousArgs: route?.settings?.arguments)); | 137 | + previousArgs: route?.settings?.arguments); |
138 | + | ||
139 | + if (routing != null) { | ||
140 | + routing(routeSend); | ||
141 | + } | ||
142 | + Get.setRouting(routeSend); | ||
108 | } | 143 | } |
109 | } | 144 | } |
1 | # Generated by pub | 1 | # Generated by pub |
2 | # See https://dart.dev/tools/pub/glossary#lockfile | 2 | # See https://dart.dev/tools/pub/glossary#lockfile |
3 | packages: | 3 | packages: |
4 | - archive: | ||
5 | - dependency: transitive | ||
6 | - description: | ||
7 | - name: archive | ||
8 | - url: "https://pub.dartlang.org" | ||
9 | - source: hosted | ||
10 | - version: "2.0.13" | ||
11 | - args: | ||
12 | - dependency: transitive | ||
13 | - description: | ||
14 | - name: args | ||
15 | - url: "https://pub.dartlang.org" | ||
16 | - source: hosted | ||
17 | - version: "1.6.0" | ||
18 | async: | 4 | async: |
19 | dependency: transitive | 5 | dependency: transitive |
20 | description: | 6 | description: |
@@ -43,20 +29,6 @@ packages: | @@ -43,20 +29,6 @@ packages: | ||
43 | url: "https://pub.dartlang.org" | 29 | url: "https://pub.dartlang.org" |
44 | source: hosted | 30 | source: hosted |
45 | version: "1.14.12" | 31 | version: "1.14.12" |
46 | - convert: | ||
47 | - dependency: transitive | ||
48 | - description: | ||
49 | - name: convert | ||
50 | - url: "https://pub.dartlang.org" | ||
51 | - source: hosted | ||
52 | - version: "2.1.1" | ||
53 | - crypto: | ||
54 | - dependency: transitive | ||
55 | - description: | ||
56 | - name: crypto | ||
57 | - url: "https://pub.dartlang.org" | ||
58 | - source: hosted | ||
59 | - version: "2.1.4" | ||
60 | flutter: | 32 | flutter: |
61 | dependency: "direct main" | 33 | dependency: "direct main" |
62 | description: flutter | 34 | description: flutter |
@@ -67,13 +39,6 @@ packages: | @@ -67,13 +39,6 @@ packages: | ||
67 | description: flutter | 39 | description: flutter |
68 | source: sdk | 40 | source: sdk |
69 | version: "0.0.0" | 41 | version: "0.0.0" |
70 | - image: | ||
71 | - dependency: transitive | ||
72 | - description: | ||
73 | - name: image | ||
74 | - url: "https://pub.dartlang.org" | ||
75 | - source: hosted | ||
76 | - version: "2.1.12" | ||
77 | matcher: | 42 | matcher: |
78 | dependency: transitive | 43 | dependency: transitive |
79 | description: | 44 | description: |
@@ -95,13 +60,6 @@ packages: | @@ -95,13 +60,6 @@ packages: | ||
95 | url: "https://pub.dartlang.org" | 60 | url: "https://pub.dartlang.org" |
96 | source: hosted | 61 | source: hosted |
97 | version: "1.6.4" | 62 | version: "1.6.4" |
98 | - petitparser: | ||
99 | - dependency: transitive | ||
100 | - description: | ||
101 | - name: petitparser | ||
102 | - url: "https://pub.dartlang.org" | ||
103 | - source: hosted | ||
104 | - version: "2.4.0" | ||
105 | quiver: | 63 | quiver: |
106 | dependency: transitive | 64 | dependency: transitive |
107 | description: | 65 | description: |
@@ -170,12 +128,5 @@ packages: | @@ -170,12 +128,5 @@ packages: | ||
170 | url: "https://pub.dartlang.org" | 128 | url: "https://pub.dartlang.org" |
171 | source: hosted | 129 | source: hosted |
172 | version: "2.0.8" | 130 | version: "2.0.8" |
173 | - xml: | ||
174 | - dependency: transitive | ||
175 | - description: | ||
176 | - name: xml | ||
177 | - url: "https://pub.dartlang.org" | ||
178 | - source: hosted | ||
179 | - version: "3.6.1" | ||
180 | sdks: | 131 | sdks: |
181 | dart: ">=2.6.0 <3.0.0" | 132 | dart: ">=2.6.0 <3.0.0" |
1 | name: get | 1 | name: get |
2 | description: Navigate between screens, display snackbars, dialogs and bottomSheets, from anywhere in your code without context with Get. | 2 | description: Navigate between screens, display snackbars, dialogs and bottomSheets, from anywhere in your code without context with Get. |
3 | -version: 1.16.0-dev | 3 | +version: 1.19.0-dev |
4 | homepage: https://github.com/jonataslaw/get | 4 | homepage: https://github.com/jonataslaw/get |
5 | 5 | ||
6 | environment: | 6 | environment: |
-
Please register or login to post a comment