Showing
9 changed files
with
512 additions
and
24 deletions
@@ -117,5 +117,32 @@ | @@ -117,5 +117,32 @@ | ||
117 | ## [1.8.1] | 117 | ## [1.8.1] |
118 | -Fix new snackbar features | 118 | -Fix new snackbar features |
119 | 119 | ||
120 | +## [1.9.0] | ||
121 | + -Added: Navigator observer | ||
122 | + -Added: Get.args to named routes | ||
123 | + -Improve snackbar performance | ||
124 | + | ||
125 | +## [1.9.1] | ||
126 | + -Fix typo on snackbar route | ||
127 | + | ||
128 | +## [1.9.2] | ||
129 | + -Added docs to GetObserver | ||
130 | + | ||
131 | +## [1.10.0] | ||
132 | + -Added backdrop | ||
133 | + | ||
134 | +## [1.10.1] | ||
135 | + -Backdrop improvement | ||
136 | + | ||
137 | +## [1.10.2] | ||
138 | + -Improve snackbar text color | ||
139 | + | ||
140 | +## [1.10.3] | ||
141 | + -Improve default color from dialogs | ||
142 | + | ||
143 | +## [1.10.4] | ||
144 | + -Improve Get.offAll() - predicate now is optional | ||
145 | + | ||
146 | + | ||
120 | 147 | ||
121 | 148 |
@@ -9,13 +9,15 @@ I worked on a pull to fix it in the framework, and seeing how things work I real | @@ -9,13 +9,15 @@ I worked on a pull to fix it in the framework, and seeing how things work I real | ||
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, | 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. | 10 | increasing your productivity, and eliminating all the bugs present in Flutter's default navigation altogether. |
11 | 11 | ||
12 | +##### If you use MODULAR, you can to use [GET MODULAR](https://pub.dev/packages/get_modular) | ||
13 | + | ||
12 | ## How to use? | 14 | ## How to use? |
13 | 15 | ||
14 | Add this to your package's pubspec.yaml file: | 16 | Add this to your package's pubspec.yaml file: |
15 | 17 | ||
16 | ``` | 18 | ``` |
17 | dependencies: | 19 | dependencies: |
18 | - get: ^1.9.2 | 20 | + get: ^1.10.4 |
19 | ``` | 21 | ``` |
20 | 22 | ||
21 | And import it: | 23 | And import it: |
@@ -51,7 +53,7 @@ Get.off(NextScreen()); | @@ -51,7 +53,7 @@ Get.off(NextScreen()); | ||
51 | To go to the next screen and cancel all previous routes (useful in shopping carts, polls, and tests) | 53 | To go to the next screen and cancel all previous routes (useful in shopping carts, polls, and tests) |
52 | 54 | ||
53 | ```dart | 55 | ```dart |
54 | -Get.offAll(NextScreen(), (route) => false); | 56 | +Get.offAll(NextScreen()); |
55 | ``` | 57 | ``` |
56 | 58 | ||
57 | To navigate to the next route, and receive or update data as soon as you return from it: | 59 | To navigate to the next route, and receive or update data as soon as you return from it: |
@@ -195,7 +197,7 @@ Get.offNamed("/NextScreen"); | @@ -195,7 +197,7 @@ Get.offNamed("/NextScreen"); | ||
195 | ``` | 197 | ``` |
196 | To navigate and remove all previous screens from the tree. | 198 | To navigate and remove all previous screens from the tree. |
197 | ```dart | 199 | ```dart |
198 | -Get.offAllNamed("/NextScreen", (route) => false); | 200 | +Get.offAllNamed("/NextScreen"); |
199 | ``` | 201 | ``` |
200 | 202 | ||
201 | ## Using with Named Routes and And offering full flutter_web support (REQUIRED FOR NAMED ROUTES): | 203 | ## Using with Named Routes and And offering full flutter_web support (REQUIRED FOR NAMED ROUTES): |
@@ -213,7 +215,7 @@ void main() { | @@ -213,7 +215,7 @@ void main() { | ||
213 | } | 215 | } |
214 | ``` | 216 | ``` |
215 | #### Middleware | 217 | #### Middleware |
216 | -If you want to hear Get events to trigger actions, you can add a GetObserver to your materialApp. This is extremely useful for triggering events whenever a specific Screen is displayed on the screen. Currently on Flutter you would have to put the event on initState and wait for a possible response in a navigator.pop (context); to get that. But with Get, this is extremely simple! | 218 | +If you want listen Get events to trigger actions, you can add a GetObserver to your materialApp. This is extremely useful for triggering events whenever a specific Screen is displayed on the screen. Currently on Flutter you would have to put the event on initState and wait for a possible response in a navigator.pop (context); to get that. But with Get, this is extremely simple! |
217 | 219 | ||
218 | ##### add GetObserver(); | 220 | ##### add GetObserver(); |
219 | ```dart | 221 | ```dart |
@@ -5,3 +5,4 @@ export 'src/routes.dart'; | @@ -5,3 +5,4 @@ export 'src/routes.dart'; | ||
5 | export 'src/snack.dart'; | 5 | export 'src/snack.dart'; |
6 | export 'src/bottomsheet.dart'; | 6 | export 'src/bottomsheet.dart'; |
7 | export 'src/snack_route.dart'; | 7 | export 'src/snack_route.dart'; |
8 | +export 'src/route_observer.dart'; |
lib/src/backdrop_blur.dart
0 → 100644
1 | +import 'dart:math' as math; | ||
2 | +import 'dart:ui' as ui; | ||
3 | + | ||
4 | +import 'package:flutter/material.dart'; | ||
5 | +import 'package:flutter/scheduler.dart'; | ||
6 | + | ||
7 | +class RippleBackdropAnimatePage extends StatefulWidget { | ||
8 | + const RippleBackdropAnimatePage({ | ||
9 | + Key key, | ||
10 | + this.child, | ||
11 | + this.childFade = false, | ||
12 | + this.duration = 300, | ||
13 | + this.blurRadius = 15.0, | ||
14 | + this.bottomButton, | ||
15 | + this.bottomHeight = kBottomNavigationBarHeight, | ||
16 | + this.bottomButtonRotate = true, | ||
17 | + this.bottomButtonRotateDegree = 45.0, | ||
18 | + }) : super(key: key); | ||
19 | + | ||
20 | + /// Child for page. | ||
21 | + final Widget child; | ||
22 | + | ||
23 | + /// When enabled, [child] will fade in when animation is going and fade out when popping. | ||
24 | + /// [false] is by default. | ||
25 | + final bool childFade; | ||
26 | + | ||
27 | + /// Animation's duration, | ||
28 | + /// including [Navigator.push], [Navigator.pop]. | ||
29 | + final int duration; | ||
30 | + | ||
31 | + /// Blur radius for [BackdropFilter]. | ||
32 | + final double blurRadius; | ||
33 | + | ||
34 | + /// [Widget] for bottom of the page. | ||
35 | + final Widget bottomButton; | ||
36 | + | ||
37 | + /// The height which [bottomButton] will occupy. | ||
38 | + /// [kBottomNavigationBarHeight] is by default. | ||
39 | + final double bottomHeight; | ||
40 | + | ||
41 | + /// When enabled, [bottomButton] will rotate when to animation is going. | ||
42 | + /// [true] is by default. | ||
43 | + final bool bottomButtonRotate; | ||
44 | + | ||
45 | + /// The degree which [bottomButton] will rotate. | ||
46 | + /// 45.0 is by default. | ||
47 | + final double bottomButtonRotateDegree; | ||
48 | + | ||
49 | + @override | ||
50 | + _RippleBackdropAnimatePageState createState() => | ||
51 | + _RippleBackdropAnimatePageState(); | ||
52 | +} | ||
53 | + | ||
54 | +class _RippleBackdropAnimatePageState extends State<RippleBackdropAnimatePage> | ||
55 | + with TickerProviderStateMixin { | ||
56 | + /// Boolean to prevent duplicate pop. | ||
57 | + bool _popping = false; | ||
58 | + | ||
59 | + /// Animation. | ||
60 | + int _animateDuration; | ||
61 | + double _backdropFilterSize = 0.0; | ||
62 | + double _popButtonOpacity = 0.0; | ||
63 | + double _popButtonRotateAngle = 0.0; | ||
64 | + Animation<double> _backDropFilterAnimation; | ||
65 | + AnimationController _backDropFilterController; | ||
66 | + Animation<double> _popButtonAnimation; | ||
67 | + AnimationController _popButtonController; | ||
68 | + Animation<double> _popButtonOpacityAnimation; | ||
69 | + AnimationController _popButtonOpacityController; | ||
70 | + | ||
71 | + @override | ||
72 | + void initState() { | ||
73 | + _animateDuration = widget.duration; | ||
74 | + SchedulerBinding.instance | ||
75 | + .addPostFrameCallback((_) => backDropFilterAnimate(context, true)); | ||
76 | + super.initState(); | ||
77 | + } | ||
78 | + | ||
79 | + @override | ||
80 | + void dispose() { | ||
81 | + _backDropFilterController?.dispose(); | ||
82 | + _popButtonController?.dispose(); | ||
83 | + super.dispose(); | ||
84 | + } | ||
85 | + | ||
86 | + double pythagoreanTheorem(double short, double long) { | ||
87 | + return math.sqrt(math.pow(short, 2) + math.pow(long, 2)); | ||
88 | + } | ||
89 | + | ||
90 | + void popButtonAnimate(context, bool forward) { | ||
91 | + if (!forward) { | ||
92 | + _popButtonController?.stop(); | ||
93 | + _popButtonOpacityController?.stop(); | ||
94 | + } | ||
95 | + final double rotateDegree = | ||
96 | + widget.bottomButtonRotateDegree * (math.pi / 180) * 3; | ||
97 | + | ||
98 | + _popButtonOpacityController = _popButtonController = AnimationController( | ||
99 | + duration: Duration(milliseconds: _animateDuration), | ||
100 | + vsync: this, | ||
101 | + ); | ||
102 | + Animation _popButtonCurve = CurvedAnimation( | ||
103 | + parent: _popButtonController, | ||
104 | + curve: Curves.easeInOut, | ||
105 | + ); | ||
106 | + _popButtonAnimation = Tween( | ||
107 | + begin: forward ? 0.0 : _popButtonRotateAngle, | ||
108 | + end: forward ? rotateDegree : 0.0, | ||
109 | + ).animate(_popButtonCurve) | ||
110 | + ..addListener(() { | ||
111 | + setState(() { | ||
112 | + _popButtonRotateAngle = _popButtonAnimation.value; | ||
113 | + }); | ||
114 | + }); | ||
115 | + _popButtonOpacityAnimation = Tween( | ||
116 | + begin: forward ? 0.0 : _popButtonOpacity, | ||
117 | + end: forward ? 1.0 : 0.0, | ||
118 | + ).animate(_popButtonCurve) | ||
119 | + ..addListener(() { | ||
120 | + setState(() { | ||
121 | + _popButtonOpacity = _popButtonOpacityAnimation.value; | ||
122 | + }); | ||
123 | + }); | ||
124 | + _popButtonController.forward(); | ||
125 | + _popButtonOpacityController.forward(); | ||
126 | + } | ||
127 | + | ||
128 | + Future backDropFilterAnimate(BuildContext context, bool forward) async { | ||
129 | + final MediaQueryData m = MediaQuery.of(context); | ||
130 | + final Size s = m.size; | ||
131 | + final double r = | ||
132 | + pythagoreanTheorem(s.width, s.height * 2 + m.padding.top) / 2; | ||
133 | + if (!forward) _backDropFilterController?.stop(); | ||
134 | + popButtonAnimate(context, forward); | ||
135 | + | ||
136 | + _backDropFilterController = AnimationController( | ||
137 | + duration: Duration(milliseconds: _animateDuration), | ||
138 | + vsync: this, | ||
139 | + ); | ||
140 | + Animation _backDropFilterCurve = CurvedAnimation( | ||
141 | + parent: _backDropFilterController, | ||
142 | + curve: forward ? Curves.easeInOut : Curves.easeIn, | ||
143 | + ); | ||
144 | + _backDropFilterAnimation = Tween( | ||
145 | + begin: forward ? 0.0 : _backdropFilterSize, | ||
146 | + end: forward ? r * 2 : 0.0, | ||
147 | + ).animate(_backDropFilterCurve) | ||
148 | + ..addListener(() { | ||
149 | + setState(() { | ||
150 | + _backdropFilterSize = _backDropFilterAnimation.value; | ||
151 | + }); | ||
152 | + }); | ||
153 | + await _backDropFilterController.forward(); | ||
154 | + } | ||
155 | + | ||
156 | + Widget popButton() { | ||
157 | + Widget button = widget.bottomButton ?? Icon(Icons.add, color: Colors.grey); | ||
158 | + if (widget.bottomButtonRotate) { | ||
159 | + button = Transform.rotate( | ||
160 | + angle: _popButtonRotateAngle, | ||
161 | + child: button, | ||
162 | + ); | ||
163 | + } | ||
164 | + button = Opacity( | ||
165 | + opacity: _popButtonOpacity, | ||
166 | + child: SizedBox( | ||
167 | + width: widget.bottomHeight, | ||
168 | + height: widget.bottomHeight, | ||
169 | + child: Center( | ||
170 | + child: GestureDetector( | ||
171 | + behavior: HitTestBehavior.opaque, | ||
172 | + child: button, | ||
173 | + onTap: willPop, | ||
174 | + ), | ||
175 | + ), | ||
176 | + ), | ||
177 | + ); | ||
178 | + | ||
179 | + return button; | ||
180 | + } | ||
181 | + | ||
182 | + Widget wrapper(context, {Widget child}) { | ||
183 | + final MediaQueryData m = MediaQuery.of(context); | ||
184 | + final Size s = m.size; | ||
185 | + final double r = | ||
186 | + pythagoreanTheorem(s.width, s.height * 2 + m.padding.top) / 2; | ||
187 | + final double topOverflow = r - s.height; | ||
188 | + final double horizontalOverflow = r - s.width; | ||
189 | + | ||
190 | + return Stack( | ||
191 | + overflow: Overflow.visible, | ||
192 | + children: <Widget>[ | ||
193 | + Positioned( | ||
194 | + left: -horizontalOverflow, | ||
195 | + right: -horizontalOverflow, | ||
196 | + top: -topOverflow, | ||
197 | + bottom: -r, | ||
198 | + child: GestureDetector( | ||
199 | + behavior: HitTestBehavior.opaque, | ||
200 | + onTap: willPop, | ||
201 | + child: Center( | ||
202 | + child: SizedBox( | ||
203 | + width: _backdropFilterSize, | ||
204 | + height: _backdropFilterSize, | ||
205 | + child: ClipRRect( | ||
206 | + borderRadius: BorderRadius.circular(r * 2), | ||
207 | + child: BackdropFilter( | ||
208 | + filter: ui.ImageFilter.blur( | ||
209 | + sigmaX: widget.blurRadius, | ||
210 | + sigmaY: widget.blurRadius, | ||
211 | + ), | ||
212 | + child: Text(" "), | ||
213 | + ), | ||
214 | + ), | ||
215 | + ), | ||
216 | + ), | ||
217 | + ), | ||
218 | + ), | ||
219 | + Align( | ||
220 | + alignment: Alignment.topCenter, | ||
221 | + child: Container( | ||
222 | + margin: EdgeInsets.only(top: topOverflow + 10), | ||
223 | + width: s.width, | ||
224 | + height: s.height, | ||
225 | + constraints: BoxConstraints( | ||
226 | + maxWidth: s.width, | ||
227 | + maxHeight: s.height, | ||
228 | + ), | ||
229 | + child: Column( | ||
230 | + mainAxisAlignment: MainAxisAlignment.end, | ||
231 | + children: <Widget>[ | ||
232 | + Expanded( | ||
233 | + child: Opacity( | ||
234 | + opacity: widget.childFade ? _popButtonOpacity : 1.0, | ||
235 | + child: child, | ||
236 | + ), | ||
237 | + ), | ||
238 | + popButton(), | ||
239 | + ], | ||
240 | + ), | ||
241 | + ), | ||
242 | + ), | ||
243 | + ], | ||
244 | + ); | ||
245 | + } | ||
246 | + | ||
247 | + Future<bool> willPop() async { | ||
248 | + await backDropFilterAnimate(context, false); | ||
249 | + if (!_popping) { | ||
250 | + _popping = true; | ||
251 | + await Future.delayed(Duration(milliseconds: _animateDuration), () { | ||
252 | + Navigator.of(context).pop(); | ||
253 | + }); | ||
254 | + } | ||
255 | + return null; | ||
256 | + } | ||
257 | + | ||
258 | + @override | ||
259 | + Widget build(BuildContext context) { | ||
260 | + return Scaffold( | ||
261 | + backgroundColor: Colors.transparent, | ||
262 | + body: WillPopScope( | ||
263 | + onWillPop: willPop, | ||
264 | + child: wrapper( | ||
265 | + context, | ||
266 | + child: widget.child, | ||
267 | + ), | ||
268 | + ), | ||
269 | + ); | ||
270 | + } | ||
271 | +} |
@@ -43,6 +43,7 @@ Future<T> getShowGeneralDialog<T>({ | @@ -43,6 +43,7 @@ Future<T> getShowGeneralDialog<T>({ | ||
43 | assert(!barrierDismissible || barrierLabel != null); | 43 | assert(!barrierDismissible || barrierLabel != null); |
44 | return Get.key.currentState.push<T>(_DialogRoute<T>( | 44 | return Get.key.currentState.push<T>(_DialogRoute<T>( |
45 | pageBuilder: pageBuilder, | 45 | pageBuilder: pageBuilder, |
46 | + settings: RouteSettings(name: "dialog"), // REMOVE THIS IF ERROR | ||
46 | barrierDismissible: barrierDismissible, | 47 | barrierDismissible: barrierDismissible, |
47 | barrierLabel: barrierLabel, | 48 | barrierLabel: barrierLabel, |
48 | barrierColor: barrierColor, | 49 | barrierColor: barrierColor, |
lib/src/route_observer.dart
0 → 100644
1 | +import 'package:flutter/widgets.dart'; | ||
2 | + | ||
3 | +class Routing { | ||
4 | + final current; | ||
5 | + final previous; | ||
6 | + final args; | ||
7 | + final previousArgs; | ||
8 | + final removed; | ||
9 | + final bool isBack; | ||
10 | + final bool isSnackbar; | ||
11 | + final bool isBottomSheet; | ||
12 | + final bool isDialog; | ||
13 | + Routing({ | ||
14 | + this.current, | ||
15 | + this.previous, | ||
16 | + this.args, | ||
17 | + this.previousArgs, | ||
18 | + this.removed, | ||
19 | + this.isBack, | ||
20 | + this.isSnackbar, | ||
21 | + this.isBottomSheet, | ||
22 | + this.isDialog, | ||
23 | + }); | ||
24 | +} | ||
25 | + | ||
26 | +class GetObserver extends NavigatorObserver { | ||
27 | + final Function(Routing) routing; | ||
28 | + GetObserver(this.routing); | ||
29 | + @override | ||
30 | + void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { | ||
31 | + if ('${route?.settings?.name}' == 'snackbar') { | ||
32 | + print("[OPEN SNACKBAR] ${route?.settings?.name}"); | ||
33 | + } else if ('${route?.settings?.name}' == 'bottomsheet') { | ||
34 | + print("[OPEN BOTTOMSHEET] ${route?.settings?.name}"); | ||
35 | + } else if ('${route?.settings?.name}' == 'dialog') { | ||
36 | + print("[OPEN DIALOG] ${route?.settings?.name}"); | ||
37 | + } else { | ||
38 | + print("[GOING TO ROUTE] ${route?.settings?.name}"); | ||
39 | + } | ||
40 | + | ||
41 | + routing(Routing( | ||
42 | + removed: null, | ||
43 | + isBack: false, | ||
44 | + current: '${route?.settings?.name}', | ||
45 | + previous: '${previousRoute?.settings?.name}', | ||
46 | + args: route?.settings?.arguments, | ||
47 | + previousArgs: previousRoute?.settings?.arguments, | ||
48 | + isSnackbar: '${route?.settings?.name}' == 'snackbar')); | ||
49 | + } | ||
50 | + | ||
51 | + @override | ||
52 | + void didPop(Route route, Route previousRoute) { | ||
53 | + super.didPop(route, previousRoute); | ||
54 | + | ||
55 | + if ('${route?.settings?.name}' == 'snackbar') { | ||
56 | + print("[CLOSE SNACKBAR] ${route?.settings?.name}"); | ||
57 | + } else if ('${route?.settings?.name}' == 'bottomsheet') { | ||
58 | + print("[CLOSE BOTTOMSHEET] ${route?.settings?.name}"); | ||
59 | + } else if ('${route?.settings?.name}' == 'dialog') { | ||
60 | + print("[CLOSE DIALOG] ${route?.settings?.name}"); | ||
61 | + } else if ('${route?.settings?.name}' == 'snackbar') { | ||
62 | + print("[CLOSE SNACKBAR] ${route?.settings?.name}"); | ||
63 | + } else { | ||
64 | + print("[BACK ROUTE] ${route?.settings?.name}"); | ||
65 | + } | ||
66 | + | ||
67 | + routing(Routing( | ||
68 | + removed: null, | ||
69 | + isBack: true, | ||
70 | + current: '${previousRoute?.settings?.name}', | ||
71 | + previous: '${route?.settings?.name}', | ||
72 | + args: previousRoute?.settings?.arguments, | ||
73 | + previousArgs: route?.settings?.arguments, | ||
74 | + isSnackbar: '${route?.settings?.name}' == 'snackbar')); | ||
75 | + } | ||
76 | + | ||
77 | + @override | ||
78 | + void didReplace({Route newRoute, Route oldRoute}) { | ||
79 | + super.didReplace(newRoute: newRoute, oldRoute: oldRoute); | ||
80 | + print("[REPLACE ROUTE] ${oldRoute?.settings?.name}"); | ||
81 | + | ||
82 | + routing(Routing( | ||
83 | + removed: null, // add '${oldRoute?.settings?.name}' or remain null ??? | ||
84 | + isBack: false, | ||
85 | + current: '${newRoute?.settings?.name}', | ||
86 | + previous: '${oldRoute?.settings?.name}', | ||
87 | + args: newRoute?.settings?.arguments, | ||
88 | + isSnackbar: null, | ||
89 | + previousArgs: null)); | ||
90 | + } | ||
91 | + | ||
92 | + @override | ||
93 | + void didRemove(Route route, Route previousRoute) { | ||
94 | + super.didRemove(route, previousRoute); | ||
95 | + print("[REMOVING ROUTE] ${route?.settings?.name}"); | ||
96 | + | ||
97 | + routing(Routing( | ||
98 | + isBack: false, | ||
99 | + current: '${previousRoute?.settings?.name}', | ||
100 | + removed: '${route?.settings?.name}', | ||
101 | + previous: null, | ||
102 | + isSnackbar: null, | ||
103 | + args: previousRoute?.settings?.arguments, | ||
104 | + previousArgs: route?.settings?.arguments)); | ||
105 | + } | ||
106 | +} |
1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
2 | +import 'package:flutter/scheduler.dart'; | ||
3 | +import 'backdrop_blur.dart'; | ||
2 | import 'bottomsheet.dart'; | 4 | import 'bottomsheet.dart'; |
3 | import 'dialog.dart'; | 5 | import 'dialog.dart'; |
4 | import 'snack.dart'; | 6 | import 'snack.dart'; |
5 | import 'getroute.dart'; | 7 | import 'getroute.dart'; |
8 | +import 'transparent_route.dart'; | ||
6 | 9 | ||
7 | class Get { | 10 | class Get { |
8 | static Get _get; | 11 | static Get _get; |
@@ -31,11 +34,16 @@ class Get { | @@ -31,11 +34,16 @@ class Get { | ||
31 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior | 34 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior |
32 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. | 35 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. |
33 | static to(Widget page, | 36 | static to(Widget page, |
34 | - {bool rebuildRoutes = false, Transition transition = Transition.fade}) { | 37 | + {bool rebuildRoutes = false, |
38 | + Transition transition = Transition.fade, | ||
39 | + Duration duration = const Duration(milliseconds: 400)}) { | ||
35 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 40 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
36 | // when widget don't mounted | 41 | // when widget don't mounted |
37 | - return key.currentState.push( | ||
38 | - GetRoute(opaque: rebuildRoutes, page: page, transition: transition)); | 42 | + return key.currentState.push(GetRoute( |
43 | + opaque: rebuildRoutes, | ||
44 | + page: page, | ||
45 | + transition: transition, | ||
46 | + duration: duration)); | ||
39 | } | 47 | } |
40 | 48 | ||
41 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed | 49 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed |
@@ -82,16 +90,18 @@ class Get { | @@ -82,16 +90,18 @@ class Get { | ||
82 | 90 | ||
83 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. | 91 | /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. |
84 | static offAllNamed( | 92 | static offAllNamed( |
85 | - String newRouteName, | ||
86 | - RoutePredicate predicate, { | 93 | + String newRouteName, { |
94 | + RoutePredicate predicate, | ||
87 | arguments, | 95 | arguments, |
88 | }) { | 96 | }) { |
89 | - return key.currentState | ||
90 | - .pushNamedAndRemoveUntil(newRouteName, predicate, arguments: arguments); | 97 | + var route = (Route<dynamic> rota) => false; |
98 | + return key.currentState.pushNamedAndRemoveUntil( | ||
99 | + newRouteName, predicate ?? route, | ||
100 | + arguments: arguments); | ||
91 | } | 101 | } |
92 | 102 | ||
93 | /// It replaces Navigator.pop, but needs no context. | 103 | /// It replaces Navigator.pop, but needs no context. |
94 | - static back({result}) { | 104 | + static back({dynamic result}) { |
95 | return key.currentState.pop(result); | 105 | return key.currentState.pop(result); |
96 | } | 106 | } |
97 | 107 | ||
@@ -112,18 +122,24 @@ class Get { | @@ -112,18 +122,24 @@ class Get { | ||
112 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. | 122 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. |
113 | static off(Widget page, | 123 | static off(Widget page, |
114 | {bool rebuildRoutes = false, | 124 | {bool rebuildRoutes = false, |
115 | - Transition transition = Transition.rightToLeft}) { | ||
116 | - return key.currentState.pushReplacement( | ||
117 | - GetRoute(opaque: rebuildRoutes, page: page, transition: transition)); | 125 | + Transition transition = Transition.rightToLeft, |
126 | + Duration duration = const Duration(milliseconds: 400)}) { | ||
127 | + return key.currentState.pushReplacement(GetRoute( | ||
128 | + opaque: rebuildRoutes, | ||
129 | + page: page, | ||
130 | + transition: transition, | ||
131 | + duration: duration)); | ||
118 | } | 132 | } |
119 | 133 | ||
120 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context | 134 | /// It replaces Navigator.pushAndRemoveUntil, but needs no context |
121 | - static offAll(Widget page, RoutePredicate predicate, | ||
122 | - {bool rebuildRoutes = false, | 135 | + static offAll(Widget page, |
136 | + {RoutePredicate predicate, | ||
137 | + bool rebuildRoutes = false, | ||
123 | Transition transition = Transition.rightToLeft}) { | 138 | Transition transition = Transition.rightToLeft}) { |
139 | + var route = (Route<dynamic> rota) => false; | ||
124 | return key.currentState.pushAndRemoveUntil( | 140 | return key.currentState.pushAndRemoveUntil( |
125 | GetRoute(opaque: rebuildRoutes, page: page, transition: transition), | 141 | GetRoute(opaque: rebuildRoutes, page: page, transition: transition), |
126 | - predicate); | 142 | + predicate ?? route); |
127 | } | 143 | } |
128 | 144 | ||
129 | /// Show a dialog. You can choose color and opacity of background | 145 | /// Show a dialog. You can choose color and opacity of background |
@@ -137,6 +153,7 @@ class Get { | @@ -137,6 +153,7 @@ class Get { | ||
137 | assert(useRootNavigator != null); | 153 | assert(useRootNavigator != null); |
138 | final ThemeData theme = | 154 | final ThemeData theme = |
139 | Theme.of(Get.key.currentContext, shadowThemeOnly: true); | 155 | Theme.of(Get.key.currentContext, shadowThemeOnly: true); |
156 | + | ||
140 | return getShowGeneralDialog( | 157 | return getShowGeneralDialog( |
141 | pageBuilder: (BuildContext buildContext, Animation<double> animation, | 158 | pageBuilder: (BuildContext buildContext, Animation<double> animation, |
142 | Animation<double> secondaryAnimation) { | 159 | Animation<double> secondaryAnimation) { |
@@ -208,10 +225,40 @@ class Get { | @@ -208,10 +225,40 @@ class Get { | ||
208 | clipBehavior: clipBehavior, | 225 | clipBehavior: clipBehavior, |
209 | isDismissible: isDismissible, | 226 | isDismissible: isDismissible, |
210 | modalBarrierColor: barrierColor, | 227 | modalBarrierColor: barrierColor, |
228 | + settings: RouteSettings(name: "bottomsheet"), | ||
211 | enableDrag: enableDrag, | 229 | enableDrag: enableDrag, |
212 | )); | 230 | )); |
213 | } | 231 | } |
214 | 232 | ||
233 | + /// get arguments from current screen. You need of context | ||
234 | + static args(context) { | ||
235 | + return ModalRoute.of(context).settings.arguments; | ||
236 | + } | ||
237 | + | ||
238 | + static backdrop(Widget child, | ||
239 | + {double radius = 20.0, | ||
240 | + double blurRadius: 20.0, | ||
241 | + int duration = 300, | ||
242 | + Transition transition = Transition.fade, | ||
243 | + Widget bottomButton = const Icon(Icons.visibility), | ||
244 | + double bottomHeight = 60.0, | ||
245 | + bool bottomButtonRotate = false}) { | ||
246 | + final page = RippleBackdropAnimatePage( | ||
247 | + child: child, | ||
248 | + childFade: true, | ||
249 | + duration: duration, | ||
250 | + blurRadius: blurRadius, | ||
251 | + bottomButton: bottomButton, | ||
252 | + bottomHeight: bottomHeight, | ||
253 | + bottomButtonRotate: bottomButtonRotate, | ||
254 | + ); | ||
255 | + | ||
256 | + return key.currentState | ||
257 | + .push(TransparentRoute(builder: (BuildContext context) { | ||
258 | + return page; | ||
259 | + })); | ||
260 | + } | ||
261 | + | ||
215 | static snackbar(title, message, | 262 | static snackbar(title, message, |
216 | {Color colorText, | 263 | {Color colorText, |
217 | Duration duration, | 264 | Duration duration, |
@@ -246,14 +293,14 @@ class Get { | @@ -246,14 +293,14 @@ class Get { | ||
246 | double overlayBlur, | 293 | double overlayBlur, |
247 | Color overlayColor, | 294 | Color overlayColor, |
248 | Form userInputForm}) { | 295 | Form userInputForm}) { |
249 | - // if (key.currentState.mounted) | 296 | + SchedulerBinding.instance.addPostFrameCallback((_) { |
297 | + final Color defaultColor = IconTheme.of(Get.key.currentContext).color; | ||
250 | return GetBar( | 298 | return GetBar( |
251 | titleText: titleText ?? | 299 | titleText: titleText ?? |
252 | Text( | 300 | Text( |
253 | title, | 301 | title, |
254 | style: TextStyle( | 302 | style: TextStyle( |
255 | - color: | ||
256 | - colorText ?? Theme.of(Get.key.currentContext).accentColor, | 303 | + color: colorText ?? defaultColor, |
257 | fontWeight: FontWeight.w800, | 304 | fontWeight: FontWeight.w800, |
258 | fontSize: 16), | 305 | fontSize: 16), |
259 | ), | 306 | ), |
@@ -261,8 +308,7 @@ class Get { | @@ -261,8 +308,7 @@ class Get { | ||
261 | Text( | 308 | Text( |
262 | message, | 309 | message, |
263 | style: TextStyle( | 310 | style: TextStyle( |
264 | - color: | ||
265 | - colorText ?? Theme.of(Get.key.currentContext).accentColor, | 311 | + color: colorText ?? defaultColor, |
266 | fontWeight: FontWeight.w300, | 312 | fontWeight: FontWeight.w300, |
267 | fontSize: 14), | 313 | fontSize: 14), |
268 | ), | 314 | ), |
@@ -297,5 +343,6 @@ class Get { | @@ -297,5 +343,6 @@ class Get { | ||
297 | overlayColor: overlayColor ?? Colors.transparent, | 343 | overlayColor: overlayColor ?? Colors.transparent, |
298 | userInputForm: userInputForm) | 344 | userInputForm: userInputForm) |
299 | ..show(); | 345 | ..show(); |
346 | + }); | ||
300 | } | 347 | } |
301 | } | 348 | } |
lib/src/transparent_route.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | + | ||
3 | +class TransparentRoute extends PageRoute<void> { | ||
4 | + TransparentRoute({ | ||
5 | + @required this.builder, | ||
6 | + RouteSettings settings, | ||
7 | + }) : assert(builder != null), | ||
8 | + super(settings: settings, fullscreenDialog: false); | ||
9 | + | ||
10 | + final WidgetBuilder builder; | ||
11 | + | ||
12 | + @override | ||
13 | + bool get opaque => false; | ||
14 | + @override | ||
15 | + Color get barrierColor => null; | ||
16 | + @override | ||
17 | + String get barrierLabel => null; | ||
18 | + @override | ||
19 | + bool get maintainState => true; | ||
20 | + @override | ||
21 | + Duration get transitionDuration => Duration.zero; | ||
22 | + | ||
23 | + @override | ||
24 | + Widget buildPage(BuildContext context, Animation<double> animation, | ||
25 | + Animation<double> secondaryAnimation) { | ||
26 | + final result = builder(context); | ||
27 | + return Semantics( | ||
28 | + scopesRoute: true, | ||
29 | + explicitChildNodes: true, | ||
30 | + child: result, | ||
31 | + ); | ||
32 | + } | ||
33 | +} |
1 | name: get | 1 | name: get |
2 | description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars easily with no context. | 2 | description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars easily with no context. |
3 | -version: 1.8.1 | 3 | +version: 1.10.4 |
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