Showing
9 changed files
with
645 additions
and
118 deletions
@@ -48,7 +48,7 @@ | @@ -48,7 +48,7 @@ | ||
48 | 48 | ||
49 | ## [1.4.0] | 49 | ## [1.4.0] |
50 | 50 | ||
51 | -- Added Get.removeRoute // remove one route. | 51 | +- Added Get.removeRoute // ability to remove one route. |
52 | Get.until // back repeatedly until the predicate returns true. | 52 | Get.until // back repeatedly until the predicate returns true. |
53 | Get.offUntil // go to next route and remove all the previous routes until the predicate returns true. | 53 | Get.offUntil // go to next route and remove all the previous routes until the predicate returns true. |
54 | Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true. | 54 | Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true. |
@@ -85,3 +85,21 @@ | @@ -85,3 +85,21 @@ | ||
85 | ## [1.6.3] | 85 | ## [1.6.3] |
86 | 86 | ||
87 | - Clean code. | 87 | - Clean code. |
88 | + | ||
89 | +## [1.6.4] | ||
90 | + | ||
91 | + - Improve performance. | ||
92 | + | ||
93 | +## [1.7.0] | ||
94 | + | ||
95 | + - Improve geral performance. Get.to Wrap now consumes even less RAM and CPU. In an application with 20 screens, it obtained 82% less RAM usage compared to the traditional method Navigator.push and had a CPU normalization of 23% in a Moto z2, against 64% CPU usage in Navigator.push with MaterialPageRoute. Test it for yourself! | ||
96 | + - Added BottomSheet with no context | ||
97 | + - Added modern Blur Snackbar | ||
98 | + - Added customs transitions | ||
99 | + - Improve dialogs performance | ||
100 | + | ||
101 | + ## [1.7.1] | ||
102 | + -Fix docs | ||
103 | + | ||
104 | + | ||
105 | + |
@@ -15,7 +15,7 @@ Add this to your package's pubspec.yaml file: | @@ -15,7 +15,7 @@ Add this to your package's pubspec.yaml file: | ||
15 | 15 | ||
16 | ``` | 16 | ``` |
17 | dependencies: | 17 | dependencies: |
18 | - get: ^1.6.3 | 18 | + get: ^1.7.1 |
19 | ``` | 19 | ``` |
20 | 20 | ||
21 | And import it: | 21 | And import it: |
@@ -68,6 +68,17 @@ ex: | @@ -68,6 +68,17 @@ ex: | ||
68 | ```dart | 68 | ```dart |
69 | if(data == 'sucess') madeAnything(); | 69 | if(data == 'sucess') madeAnything(); |
70 | ``` | 70 | ``` |
71 | +Others methods: | ||
72 | +Get.removeRoute // remove one route. | ||
73 | +Get.until // back repeatedly until the predicate returns true. | ||
74 | +Get.offUntil // go to next route and remove all the previous routes until the predicate returns true. | ||
75 | +Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true. | ||
76 | + | ||
77 | + | ||
78 | +To show a modern snackbar: | ||
79 | +```dart | ||
80 | +Get.snackbar('Hi', 'i am a modern snackbar'); | ||
81 | + | ||
71 | To open dialog: | 82 | To open dialog: |
72 | 83 | ||
73 | ```dart | 84 | ```dart |
@@ -91,25 +102,23 @@ To open default dialog: | @@ -91,25 +102,23 @@ To open default dialog: | ||
91 | ``` | 102 | ``` |
92 | 103 | ||
93 | To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, | 104 | To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, |
94 | -but with Get, all you have to do is call your SnackBar from anywhere in your code! No context, no cliche code! | 105 | +but with Get, all you have to do is call your SnackBar from anywhere in your code and and customize it however you want! |
95 | 106 | ||
96 | ```dart | 107 | ```dart |
97 | GetBar( | 108 | GetBar( |
98 | title: "Hey i'm a Get SnackBar!", | 109 | title: "Hey i'm a Get SnackBar!", |
99 | message: | 110 | message: |
100 | "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", | 111 | "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", |
112 | + icon: Icon(Icons.alarm), | ||
113 | + shouldIconPulse: true, | ||
114 | + onTap:(){}, | ||
115 | + barBlur: 20, | ||
116 | + isDismissible: true, | ||
101 | duration: Duration(seconds: 3), | 117 | duration: Duration(seconds: 3), |
102 | )..show(); | 118 | )..show(); |
103 | ``` | 119 | ``` |
104 | -Plus, the default SnackBar is completely inflexible, while GetBar lets you change the color, shape, opacity, and anything else you want! | ||
105 | 120 | ||
106 | 121 | ||
107 | -Others methods: | ||
108 | -Get.removeRoute // remove one route. | ||
109 | -Get.until // back repeatedly until the predicate returns true. | ||
110 | -Get.offUntil // go to next route and remove all the previous routes until the predicate returns true. | ||
111 | -Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true. | ||
112 | - | ||
113 | ### That's it, you've learned how to navigate between routes the default way. | 122 | ### That's it, you've learned how to navigate between routes the default way. |
114 | 123 | ||
115 | However, for people who like more organized code who want to navigate with named routes, or for Flutter_web Developers who want the url to show exactly which route is being shown, and want the page refresh not to affect the state of the routes. On your site, we give you a much more elegant and functional solution. Yeah, the default navigation doesn't fully support Flutter_web, but Get does !!!! | 124 | However, for people who like more organized code who want to navigate with named routes, or for Flutter_web Developers who want the url to show exactly which route is being shown, and want the page refresh not to affect the state of the routes. On your site, we give you a much more elegant and functional solution. Yeah, the default navigation doesn't fully support Flutter_web, but Get does !!!! |
@@ -192,7 +201,9 @@ class FirstRoute extends StatelessWidget { | @@ -192,7 +201,9 @@ class FirstRoute extends StatelessWidget { | ||
192 | icon: Icon(Icons.add), | 201 | icon: Icon(Icons.add), |
193 | onPressed: () { | 202 | onPressed: () { |
194 | GetBar( | 203 | GetBar( |
195 | - title: "Hi!", message: "i'm a Get SnackBar!", | 204 | + title: "Hey i'm a Get SnackBar!", |
205 | + message: | ||
206 | + "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", | ||
196 | duration: Duration(seconds: 3), | 207 | duration: Duration(seconds: 3), |
197 | )..show(); | 208 | )..show(); |
198 | }, | 209 | }, |
@@ -3,4 +3,5 @@ library get; | @@ -3,4 +3,5 @@ library get; | ||
3 | export 'src/getroute.dart'; | 3 | export 'src/getroute.dart'; |
4 | export 'src/routes.dart'; | 4 | export 'src/routes.dart'; |
5 | export 'src/snack.dart'; | 5 | export 'src/snack.dart'; |
6 | +export 'src/bottomsheet.dart'; | ||
6 | export 'src/snack_route.dart'; | 7 | export 'src/snack_route.dart'; |
lib/src/bottomsheet.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | + | ||
3 | +class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
4 | + GetModalBottomSheetRoute({ | ||
5 | + this.builder, | ||
6 | + this.theme, | ||
7 | + this.barrierLabel, | ||
8 | + this.backgroundColor, | ||
9 | + this.elevation, | ||
10 | + this.shape, | ||
11 | + this.clipBehavior, | ||
12 | + this.modalBarrierColor, | ||
13 | + this.isDismissible = true, | ||
14 | + this.enableDrag = true, | ||
15 | + @required this.isScrollControlled, | ||
16 | + RouteSettings settings, | ||
17 | + }) : assert(isScrollControlled != null), | ||
18 | + assert(isDismissible != null), | ||
19 | + assert(enableDrag != null), | ||
20 | + super(settings: settings); | ||
21 | + | ||
22 | + final WidgetBuilder builder; | ||
23 | + final ThemeData theme; | ||
24 | + final bool isScrollControlled; | ||
25 | + final Color backgroundColor; | ||
26 | + final double elevation; | ||
27 | + final ShapeBorder shape; | ||
28 | + final Clip clipBehavior; | ||
29 | + final Color modalBarrierColor; | ||
30 | + final bool isDismissible; | ||
31 | + final bool enableDrag; | ||
32 | + | ||
33 | + @override | ||
34 | + Duration get transitionDuration => Duration(milliseconds: 700); | ||
35 | + | ||
36 | + @override | ||
37 | + bool get barrierDismissible => isDismissible; | ||
38 | + | ||
39 | + @override | ||
40 | + final String barrierLabel; | ||
41 | + | ||
42 | + @override | ||
43 | + Color get barrierColor => modalBarrierColor ?? Colors.black54; | ||
44 | + | ||
45 | + AnimationController _animationController; | ||
46 | + | ||
47 | + @override | ||
48 | + AnimationController createAnimationController() { | ||
49 | + assert(_animationController == null); | ||
50 | + _animationController = | ||
51 | + BottomSheet.createAnimationController(navigator.overlay); | ||
52 | + return _animationController; | ||
53 | + } | ||
54 | + | ||
55 | + @override | ||
56 | + Widget buildPage(BuildContext context, Animation<double> animation, | ||
57 | + Animation<double> secondaryAnimation) { | ||
58 | + final BottomSheetThemeData sheetTheme = | ||
59 | + theme?.bottomSheetTheme ?? Theme.of(context).bottomSheetTheme; | ||
60 | + // By definition, the bottom sheet is aligned to the bottom of the page | ||
61 | + // and isn't exposed to the top padding of the MediaQuery. | ||
62 | + Widget bottomSheet = MediaQuery.removePadding( | ||
63 | + context: context, | ||
64 | + removeTop: true, | ||
65 | + child: _GetModalBottomSheet<T>( | ||
66 | + route: this, | ||
67 | + backgroundColor: backgroundColor ?? | ||
68 | + sheetTheme?.modalBackgroundColor ?? | ||
69 | + sheetTheme?.backgroundColor, | ||
70 | + elevation: | ||
71 | + elevation ?? sheetTheme?.modalElevation ?? sheetTheme?.elevation, | ||
72 | + shape: shape, | ||
73 | + clipBehavior: clipBehavior, | ||
74 | + isScrollControlled: isScrollControlled, | ||
75 | + enableDrag: enableDrag, | ||
76 | + ), | ||
77 | + ); | ||
78 | + if (theme != null) bottomSheet = Theme(data: theme, child: bottomSheet); | ||
79 | + return bottomSheet; | ||
80 | + } | ||
81 | +} | ||
82 | + | ||
83 | +class _GetModalBottomSheet<T> extends StatefulWidget { | ||
84 | + const _GetModalBottomSheet({ | ||
85 | + Key key, | ||
86 | + this.route, | ||
87 | + this.backgroundColor, | ||
88 | + this.elevation, | ||
89 | + this.shape, | ||
90 | + this.clipBehavior, | ||
91 | + this.isScrollControlled = false, | ||
92 | + this.enableDrag = true, | ||
93 | + }) : assert(isScrollControlled != null), | ||
94 | + assert(enableDrag != null), | ||
95 | + super(key: key); | ||
96 | + | ||
97 | + final GetModalBottomSheetRoute<T> route; | ||
98 | + final bool isScrollControlled; | ||
99 | + final Color backgroundColor; | ||
100 | + final double elevation; | ||
101 | + final ShapeBorder shape; | ||
102 | + final Clip clipBehavior; | ||
103 | + final bool enableDrag; | ||
104 | + | ||
105 | + @override | ||
106 | + _GetModalBottomSheetState<T> createState() => _GetModalBottomSheetState<T>(); | ||
107 | +} | ||
108 | + | ||
109 | +class _GetModalBottomSheetState<T> extends State<_GetModalBottomSheet<T>> { | ||
110 | + String _getRouteLabel(MaterialLocalizations localizations) { | ||
111 | + switch (Theme.of(context).platform) { | ||
112 | + case TargetPlatform.iOS: | ||
113 | + case TargetPlatform.macOS: | ||
114 | + return ''; | ||
115 | + case TargetPlatform.android: | ||
116 | + case TargetPlatform.fuchsia: | ||
117 | + return localizations.dialogLabel; | ||
118 | + } | ||
119 | + return null; | ||
120 | + } | ||
121 | + | ||
122 | + @override | ||
123 | + Widget build(BuildContext context) { | ||
124 | + assert(debugCheckHasMediaQuery(context)); | ||
125 | + assert(debugCheckHasMaterialLocalizations(context)); | ||
126 | + final MediaQueryData mediaQuery = MediaQuery.of(context); | ||
127 | + final MaterialLocalizations localizations = | ||
128 | + MaterialLocalizations.of(context); | ||
129 | + final String routeLabel = _getRouteLabel(localizations); | ||
130 | + | ||
131 | + return AnimatedBuilder( | ||
132 | + animation: widget.route.animation, | ||
133 | + builder: (BuildContext context, Widget child) { | ||
134 | + // Disable the initial animation when accessible navigation is on so | ||
135 | + // that the semantics are added to the tree at the correct time. | ||
136 | + final double animationValue = mediaQuery.accessibleNavigation | ||
137 | + ? 1.0 | ||
138 | + : widget.route.animation.value; | ||
139 | + return Semantics( | ||
140 | + scopesRoute: true, | ||
141 | + namesRoute: true, | ||
142 | + label: routeLabel, | ||
143 | + explicitChildNodes: true, | ||
144 | + child: ClipRect( | ||
145 | + child: CustomSingleChildLayout( | ||
146 | + delegate: _GetModalBottomSheetLayout( | ||
147 | + animationValue, widget.isScrollControlled), | ||
148 | + child: BottomSheet( | ||
149 | + animationController: widget.route._animationController, | ||
150 | + onClosing: () { | ||
151 | + if (widget.route.isCurrent) { | ||
152 | + Navigator.pop(context); | ||
153 | + } | ||
154 | + }, | ||
155 | + builder: widget.route.builder, | ||
156 | + backgroundColor: widget.backgroundColor, | ||
157 | + elevation: widget.elevation, | ||
158 | + shape: widget.shape, | ||
159 | + clipBehavior: widget.clipBehavior, | ||
160 | + enableDrag: widget.enableDrag, | ||
161 | + ), | ||
162 | + ), | ||
163 | + ), | ||
164 | + ); | ||
165 | + }, | ||
166 | + ); | ||
167 | + } | ||
168 | +} | ||
169 | + | ||
170 | +class _GetModalBottomSheetLayout extends SingleChildLayoutDelegate { | ||
171 | + _GetModalBottomSheetLayout(this.progress, this.isScrollControlled); | ||
172 | + | ||
173 | + final double progress; | ||
174 | + final bool isScrollControlled; | ||
175 | + | ||
176 | + @override | ||
177 | + BoxConstraints getConstraintsForChild(BoxConstraints constraints) { | ||
178 | + return BoxConstraints( | ||
179 | + minWidth: constraints.maxWidth, | ||
180 | + maxWidth: constraints.maxWidth, | ||
181 | + minHeight: 0.0, | ||
182 | + maxHeight: isScrollControlled | ||
183 | + ? constraints.maxHeight | ||
184 | + : constraints.maxHeight * 9.0 / 16.0, | ||
185 | + ); | ||
186 | + } | ||
187 | + | ||
188 | + @override | ||
189 | + Offset getPositionForChild(Size size, Size childSize) { | ||
190 | + return Offset(0.0, size.height - childSize.height * progress); | ||
191 | + } | ||
192 | + | ||
193 | + @override | ||
194 | + bool shouldRelayout(_GetModalBottomSheetLayout oldDelegate) { | ||
195 | + return progress != oldDelegate.progress; | ||
196 | + } | ||
197 | +} |
1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
2 | -import 'package:get/src/routes.dart'; | ||
3 | - | ||
4 | -class DialogGet extends StatelessWidget { | ||
5 | - final Widget child; | ||
6 | - final color; | ||
7 | - final double opacity; | ||
8 | - | ||
9 | - const DialogGet({Key key, this.child, this.color, this.opacity = 0.5}) | ||
10 | - : super(key: key); | ||
11 | - | ||
12 | - @override | ||
13 | - Widget build(BuildContext context) { | ||
14 | - return GestureDetector( | ||
15 | - onTap: () => Get.back(), | ||
16 | - child: Container( | ||
17 | - color: (color == null) | ||
18 | - ? Theme.of(context).accentColor.withOpacity(opacity) | ||
19 | - : color, | ||
20 | - child: GestureDetector(onTap: () => null, child: child), | ||
21 | - ), | ||
22 | - ); | ||
23 | - } | ||
24 | -} | 2 | +import 'routes.dart'; |
25 | 3 | ||
26 | class DefaultDialogGet extends StatelessWidget { | 4 | class DefaultDialogGet extends StatelessWidget { |
27 | final color; | 5 | final color; |
@@ -43,21 +21,95 @@ class DefaultDialogGet extends StatelessWidget { | @@ -43,21 +21,95 @@ class DefaultDialogGet extends StatelessWidget { | ||
43 | 21 | ||
44 | @override | 22 | @override |
45 | Widget build(BuildContext context) { | 23 | Widget build(BuildContext context) { |
46 | - return GestureDetector( | ||
47 | - onTap: () => Get.back(), | ||
48 | - child: Container( | ||
49 | - color: (color == null) | ||
50 | - ? Theme.of(context).accentColor.withOpacity(opacity) | ||
51 | - : color, | ||
52 | - child: GestureDetector( | ||
53 | - onTap: () => null, | ||
54 | - child: AlertDialog( | 24 | + return AlertDialog( |
55 | title: Text(title, textAlign: TextAlign.center), | 25 | title: Text(title, textAlign: TextAlign.center), |
56 | content: content, | 26 | content: content, |
57 | actions: <Widget>[cancel, confirm], | 27 | actions: <Widget>[cancel, confirm], |
58 | - ), | ||
59 | - ), | ||
60 | - ), | ||
61 | ); | 28 | ); |
62 | } | 29 | } |
63 | } | 30 | } |
31 | + | ||
32 | +Future<T> getShowGeneralDialog<T>({ | ||
33 | + @required RoutePageBuilder pageBuilder, | ||
34 | + bool barrierDismissible, | ||
35 | + String barrierLabel, | ||
36 | + Color barrierColor, | ||
37 | + Duration transitionDuration, | ||
38 | + RouteTransitionsBuilder transitionBuilder, | ||
39 | + bool useRootNavigator = true, | ||
40 | +}) { | ||
41 | + assert(pageBuilder != null); | ||
42 | + assert(useRootNavigator != null); | ||
43 | + assert(!barrierDismissible || barrierLabel != null); | ||
44 | + return Get.key.currentState.push<T>(_DialogRoute<T>( | ||
45 | + pageBuilder: pageBuilder, | ||
46 | + barrierDismissible: barrierDismissible, | ||
47 | + barrierLabel: barrierLabel, | ||
48 | + barrierColor: barrierColor, | ||
49 | + transitionDuration: transitionDuration, | ||
50 | + transitionBuilder: transitionBuilder, | ||
51 | + )); | ||
52 | +} | ||
53 | + | ||
54 | +class _DialogRoute<T> extends PopupRoute<T> { | ||
55 | + _DialogRoute({ | ||
56 | + @required RoutePageBuilder pageBuilder, | ||
57 | + bool barrierDismissible = true, | ||
58 | + String barrierLabel, | ||
59 | + Color barrierColor = const Color(0x80000000), | ||
60 | + Duration transitionDuration = const Duration(milliseconds: 200), | ||
61 | + RouteTransitionsBuilder transitionBuilder, | ||
62 | + RouteSettings settings, | ||
63 | + }) : assert(barrierDismissible != null), | ||
64 | + _pageBuilder = pageBuilder, | ||
65 | + _barrierDismissible = barrierDismissible, | ||
66 | + _barrierLabel = barrierLabel, | ||
67 | + _barrierColor = barrierColor, | ||
68 | + _transitionDuration = transitionDuration, | ||
69 | + _transitionBuilder = transitionBuilder, | ||
70 | + super(settings: settings); | ||
71 | + | ||
72 | + final RoutePageBuilder _pageBuilder; | ||
73 | + | ||
74 | + @override | ||
75 | + bool get barrierDismissible => _barrierDismissible; | ||
76 | + final bool _barrierDismissible; | ||
77 | + | ||
78 | + @override | ||
79 | + String get barrierLabel => _barrierLabel; | ||
80 | + final String _barrierLabel; | ||
81 | + | ||
82 | + @override | ||
83 | + Color get barrierColor => _barrierColor; | ||
84 | + final Color _barrierColor; | ||
85 | + | ||
86 | + @override | ||
87 | + Duration get transitionDuration => _transitionDuration; | ||
88 | + final Duration _transitionDuration; | ||
89 | + | ||
90 | + final RouteTransitionsBuilder _transitionBuilder; | ||
91 | + | ||
92 | + @override | ||
93 | + Widget buildPage(BuildContext context, Animation<double> animation, | ||
94 | + Animation<double> secondaryAnimation) { | ||
95 | + return Semantics( | ||
96 | + child: _pageBuilder(context, animation, secondaryAnimation), | ||
97 | + scopesRoute: true, | ||
98 | + explicitChildNodes: true, | ||
99 | + ); | ||
100 | + } | ||
101 | + | ||
102 | + @override | ||
103 | + Widget buildTransitions(BuildContext context, Animation<double> animation, | ||
104 | + Animation<double> secondaryAnimation, Widget child) { | ||
105 | + if (_transitionBuilder == null) { | ||
106 | + return FadeTransition( | ||
107 | + opacity: CurvedAnimation( | ||
108 | + parent: animation, | ||
109 | + curve: Curves.linear, | ||
110 | + ), | ||
111 | + child: child); | ||
112 | + } // Some default transition | ||
113 | + return _transitionBuilder(context, animation, secondaryAnimation, child); | ||
114 | + } | ||
115 | +} |
1 | -import 'package:flutter/cupertino.dart'; | ||
2 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
3 | 2 | ||
4 | -class GetRoute<T> extends PageRoute<T> { | ||
5 | - /// Construct a MaterialPageRoute whose contents are defined by [builder]. | ||
6 | - /// | ||
7 | - /// The values of [builder], [maintainState], and [fullScreenDialog] must not | 3 | +class GetRoute<T> extends PageRouteBuilder<T> { |
4 | + /// Construct a Modified PageRoute whose contents are defined by child. | ||
5 | + /// The values of [child], [maintainState], [opaque], and [fullScreenDialog] must not | ||
8 | /// be null. | 6 | /// be null. |
9 | GetRoute({ | 7 | GetRoute({ |
10 | - @required this.builder, | 8 | + Key key, |
11 | RouteSettings settings, | 9 | RouteSettings settings, |
12 | this.opaque = false, | 10 | this.opaque = false, |
13 | this.maintainState = true, | 11 | this.maintainState = true, |
12 | + @required this.child, | ||
13 | + @required this.transition, | ||
14 | + this.curve = Curves.linear, | ||
15 | + this.alignment, | ||
16 | + this.duration = const Duration(milliseconds: 300), | ||
14 | bool fullscreenDialog = false, | 17 | bool fullscreenDialog = false, |
15 | - }) : assert(builder != null), | 18 | + }) : assert(child != null), |
16 | assert(maintainState != null), | 19 | assert(maintainState != null), |
17 | assert(fullscreenDialog != null), | 20 | assert(fullscreenDialog != null), |
18 | assert(opaque != null), | 21 | assert(opaque != null), |
19 | - super(settings: settings, fullscreenDialog: fullscreenDialog); | ||
20 | - | ||
21 | - /// Builds the primary contents of the route. | ||
22 | - final WidgetBuilder builder; | 22 | + super( |
23 | + fullscreenDialog: fullscreenDialog, | ||
24 | + pageBuilder: (BuildContext context, Animation<double> animation, | ||
25 | + Animation<double> secondaryAnimation) { | ||
26 | + return child; | ||
27 | + }, | ||
28 | + transitionDuration: duration, | ||
29 | + settings: settings, | ||
30 | + transitionsBuilder: (BuildContext context, | ||
31 | + Animation<double> animation, | ||
32 | + Animation<double> secondaryAnimation, | ||
33 | + Widget child) { | ||
34 | + switch (transition) { | ||
35 | + case Transition.fade: | ||
36 | + return FadeTransition(opacity: animation, child: child); | ||
37 | + break; | ||
38 | + case Transition.rightToLeft: | ||
39 | + return SlideTransition( | ||
40 | + transformHitTests: false, | ||
41 | + position: new Tween<Offset>( | ||
42 | + begin: const Offset(1.0, 0.0), | ||
43 | + end: Offset.zero, | ||
44 | + ).animate(animation), | ||
45 | + child: new SlideTransition( | ||
46 | + position: new Tween<Offset>( | ||
47 | + begin: Offset.zero, | ||
48 | + end: const Offset(-1.0, 0.0), | ||
49 | + ).animate(secondaryAnimation), | ||
50 | + child: child, | ||
51 | + ), | ||
52 | + ); | ||
53 | + break; | ||
54 | + case Transition.leftToRight: | ||
55 | + return SlideTransition( | ||
56 | + transformHitTests: false, | ||
57 | + position: Tween<Offset>( | ||
58 | + begin: const Offset(-1.0, 0.0), | ||
59 | + end: Offset.zero, | ||
60 | + ).animate(animation), | ||
61 | + child: new SlideTransition( | ||
62 | + position: new Tween<Offset>( | ||
63 | + begin: Offset.zero, | ||
64 | + end: const Offset(1.0, 0.0), | ||
65 | + ).animate(secondaryAnimation), | ||
66 | + child: child, | ||
67 | + ), | ||
68 | + ); | ||
69 | + break; | ||
70 | + case Transition.upToDown: | ||
71 | + return SlideTransition( | ||
72 | + transformHitTests: false, | ||
73 | + position: Tween<Offset>( | ||
74 | + begin: const Offset(0.0, -1.0), | ||
75 | + end: Offset.zero, | ||
76 | + ).animate(animation), | ||
77 | + child: new SlideTransition( | ||
78 | + position: new Tween<Offset>( | ||
79 | + begin: Offset.zero, | ||
80 | + end: const Offset(0.0, 1.0), | ||
81 | + ).animate(secondaryAnimation), | ||
82 | + child: child, | ||
83 | + ), | ||
84 | + ); | ||
85 | + break; | ||
86 | + case Transition.downToUp: | ||
87 | + return SlideTransition( | ||
88 | + transformHitTests: false, | ||
89 | + position: Tween<Offset>( | ||
90 | + begin: const Offset(0.0, 1.0), | ||
91 | + end: Offset.zero, | ||
92 | + ).animate(animation), | ||
93 | + child: new SlideTransition( | ||
94 | + position: new Tween<Offset>( | ||
95 | + begin: Offset.zero, | ||
96 | + end: const Offset(0.0, -1.0), | ||
97 | + ).animate(secondaryAnimation), | ||
98 | + child: child, | ||
99 | + ), | ||
100 | + ); | ||
101 | + break; | ||
102 | + case Transition.scale: | ||
103 | + return ScaleTransition( | ||
104 | + alignment: alignment, | ||
105 | + scale: CurvedAnimation( | ||
106 | + parent: animation, | ||
107 | + curve: Interval( | ||
108 | + 0.00, | ||
109 | + 0.50, | ||
110 | + curve: curve, | ||
111 | + ), | ||
112 | + ), | ||
113 | + child: child, | ||
114 | + ); | ||
115 | + break; | ||
116 | + case Transition.rotate: | ||
117 | + return new RotationTransition( | ||
118 | + alignment: alignment, | ||
119 | + turns: animation, | ||
120 | + child: new ScaleTransition( | ||
121 | + alignment: alignment, | ||
122 | + scale: animation, | ||
123 | + child: FadeTransition( | ||
124 | + opacity: animation, | ||
125 | + child: child, | ||
126 | + ), | ||
127 | + ), | ||
128 | + ); | ||
129 | + break; | ||
130 | + case Transition.size: | ||
131 | + return Align( | ||
132 | + alignment: alignment, | ||
133 | + child: SizeTransition( | ||
134 | + sizeFactor: CurvedAnimation( | ||
135 | + parent: animation, | ||
136 | + curve: curve, | ||
137 | + ), | ||
138 | + child: child, | ||
139 | + ), | ||
140 | + ); | ||
141 | + break; | ||
142 | + case Transition.rightToLeftWithFade: | ||
143 | + return SlideTransition( | ||
144 | + position: Tween<Offset>( | ||
145 | + begin: const Offset(1.0, 0.0), | ||
146 | + end: Offset.zero, | ||
147 | + ).animate(animation), | ||
148 | + child: FadeTransition( | ||
149 | + opacity: animation, | ||
150 | + child: SlideTransition( | ||
151 | + position: Tween<Offset>( | ||
152 | + begin: Offset.zero, | ||
153 | + end: const Offset(-1.0, 0.0), | ||
154 | + ).animate(secondaryAnimation), | ||
155 | + child: child, | ||
156 | + ), | ||
157 | + ), | ||
158 | + ); | ||
159 | + break; | ||
160 | + case Transition.leftToRightWithFade: | ||
161 | + return SlideTransition( | ||
162 | + position: Tween<Offset>( | ||
163 | + begin: const Offset(-1.0, 0.0), | ||
164 | + end: Offset.zero, | ||
165 | + ).animate(animation), | ||
166 | + child: FadeTransition( | ||
167 | + opacity: animation, | ||
168 | + child: SlideTransition( | ||
169 | + position: Tween<Offset>( | ||
170 | + begin: Offset.zero, | ||
171 | + end: const Offset(1.0, 0.0), | ||
172 | + ).animate(secondaryAnimation), | ||
173 | + child: child, | ||
174 | + ), | ||
175 | + ), | ||
176 | + ); | ||
177 | + break; | ||
178 | + default: | ||
179 | + return FadeTransition(opacity: animation, child: child); | ||
180 | + } | ||
181 | + }); | ||
23 | 182 | ||
24 | @override | 183 | @override |
25 | final bool maintainState; | 184 | final bool maintainState; |
@@ -37,50 +196,41 @@ class GetRoute<T> extends PageRoute<T> { | @@ -37,50 +196,41 @@ class GetRoute<T> extends PageRoute<T> { | ||
37 | @override | 196 | @override |
38 | String get barrierLabel => null; | 197 | String get barrierLabel => null; |
39 | 198 | ||
40 | - @override | ||
41 | - bool canTransitionFrom(TransitionRoute<dynamic> previousRoute) { | ||
42 | - return previousRoute is GetRoute || previousRoute is CupertinoPageRoute; | ||
43 | - } | 199 | + // @override |
200 | + // bool canTransitionFrom(TransitionRoute<dynamic> previousRoute) { | ||
201 | + // return previousRoute is GetRoute || previousRoute is CupertinoPageRoute; | ||
202 | + // } | ||
44 | 203 | ||
45 | - @override | ||
46 | - bool canTransitionTo(TransitionRoute<dynamic> nextRoute) { | ||
47 | - // Don't perform outgoing animation if the next route is a fullscreen dialog. | ||
48 | - return (nextRoute is GetRoute && !nextRoute.fullscreenDialog) || | ||
49 | - (nextRoute is CupertinoPageRoute && !nextRoute.fullscreenDialog); | ||
50 | - } | 204 | + // @override |
205 | + // bool canTransitionTo(TransitionRoute<dynamic> nextRoute) { | ||
206 | + // // Don't perform outgoing animation if the next route is a fullscreen dialog. | ||
207 | + // return (nextRoute is GetRoute && !nextRoute.fullscreenDialog) || | ||
208 | + // (nextRoute is CupertinoPageRoute && !nextRoute.fullscreenDialog); | ||
209 | + // } | ||
51 | 210 | ||
52 | @override | 211 | @override |
53 | - Widget buildPage( | ||
54 | - BuildContext context, | ||
55 | - Animation<double> animation, | ||
56 | - Animation<double> secondaryAnimation, | ||
57 | - ) { | ||
58 | - final Widget result = builder(context); | ||
59 | - assert(() { | ||
60 | - if (result == null) { | ||
61 | - throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
62 | - ErrorSummary( | ||
63 | - 'The builder for route "${settings.name}" returned null.'), | ||
64 | - ErrorDescription('Route builders must never return null.') | ||
65 | - ]); | ||
66 | - } | ||
67 | - return true; | ||
68 | - }()); | ||
69 | - return Semantics( | ||
70 | - scopesRoute: true, | ||
71 | - explicitChildNodes: true, | ||
72 | - child: result, | ||
73 | - ); | ||
74 | - } | 212 | + String get debugLabel => '${super.debugLabel}(${settings.name})'; |
75 | 213 | ||
76 | - @override | ||
77 | - Widget buildTransitions(BuildContext context, Animation<double> animation, | ||
78 | - Animation<double> secondaryAnimation, Widget child) { | ||
79 | - final PageTransitionsTheme theme = Theme.of(context).pageTransitionsTheme; | ||
80 | - return theme.buildTransitions<T>( | ||
81 | - this, context, animation, secondaryAnimation, child); | ||
82 | - } | 214 | + final Widget child; |
83 | 215 | ||
84 | - @override | ||
85 | - String get debugLabel => '${super.debugLabel}(${settings.name})'; | 216 | + final Transition transition; |
217 | + | ||
218 | + final Curve curve; | ||
219 | + | ||
220 | + final Alignment alignment; | ||
221 | + | ||
222 | + final Duration duration; | ||
223 | +} | ||
224 | + | ||
225 | +enum Transition { | ||
226 | + fade, | ||
227 | + rightToLeft, | ||
228 | + leftToRight, | ||
229 | + upToDown, | ||
230 | + downToUp, | ||
231 | + scale, | ||
232 | + rotate, | ||
233 | + size, | ||
234 | + rightToLeftWithFade, | ||
235 | + leftToRightWithFade, | ||
86 | } | 236 | } |
1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
2 | -import 'package:flutter/widgets.dart'; | 2 | +import 'bottomsheet.dart'; |
3 | import 'dialog.dart'; | 3 | import 'dialog.dart'; |
4 | +import 'snack.dart'; | ||
4 | import 'getroute.dart'; | 5 | import 'getroute.dart'; |
5 | 6 | ||
6 | class Get { | 7 | class Get { |
@@ -29,9 +30,10 @@ class Get { | @@ -29,9 +30,10 @@ class Get { | ||
29 | /// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push | 30 | /// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push |
30 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior | 31 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior |
31 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. | 32 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. |
32 | - static to(Widget page, {bool rebuildRoutes = false}) { | ||
33 | - return key.currentState | ||
34 | - .push(GetRoute(opaque: rebuildRoutes, builder: (_) => page)); | 33 | + static to(Widget page, |
34 | + {bool rebuildRoutes = false, Transition transition = Transition.fade}) { | ||
35 | + return key.currentState.push( | ||
36 | + GetRoute(opaque: rebuildRoutes, child: page, transition: transition)); | ||
35 | } | 37 | } |
36 | 38 | ||
37 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed | 39 | /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed |
@@ -84,37 +86,135 @@ class Get { | @@ -84,37 +86,135 @@ class Get { | ||
84 | /// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement | 86 | /// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement |
85 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior | 87 | /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior |
86 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. | 88 | /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. |
87 | - static off(Widget page, {bool rebuildRoutes = false}) { | ||
88 | - return key.currentState | ||
89 | - .pushReplacement(GetRoute(opaque: rebuildRoutes, builder: (_) => page)); | 89 | + static off(Widget page, |
90 | + {bool rebuildRoutes = false, | ||
91 | + Transition transition = Transition.rightToLeft}) { | ||
92 | + return key.currentState.pushReplacement( | ||
93 | + GetRoute(opaque: rebuildRoutes, child: page, transition: transition)); | ||
94 | + } | ||
95 | + | ||
96 | + /// It replaces Navigator.pushAndRemoveUntil, but needs no context | ||
97 | + static offAll(Widget page, RoutePredicate predicate, | ||
98 | + {bool rebuildRoutes = false, | ||
99 | + Transition transition = Transition.rightToLeft}) { | ||
100 | + return key.currentState.pushAndRemoveUntil( | ||
101 | + GetRoute(opaque: rebuildRoutes, child: page, transition: transition), | ||
102 | + predicate); | ||
90 | } | 103 | } |
91 | 104 | ||
92 | /// Show a dialog. You can choose color and opacity of background | 105 | /// Show a dialog. You can choose color and opacity of background |
93 | - static dialog(Widget page, {Color color, double opacity = 0.5}) { | ||
94 | - Get.to(DialogGet(child: page, color: color, opacity: opacity)); | 106 | + static Future<T> dialog<T>( |
107 | + Widget child, { | ||
108 | + bool barrierDismissible = true, | ||
109 | + // WidgetBuilder builder, | ||
110 | + bool useRootNavigator = true, | ||
111 | + }) { | ||
112 | + assert(child == null | ||
113 | + // || builder == null | ||
114 | + ); | ||
115 | + assert(useRootNavigator != null); | ||
116 | + // assert(debugCheckHasMaterialLocalizations(context)); | ||
117 | + | ||
118 | + final ThemeData theme = | ||
119 | + Theme.of(Get.key.currentContext, shadowThemeOnly: true); | ||
120 | + return getShowGeneralDialog( | ||
121 | + pageBuilder: (BuildContext buildContext, Animation<double> animation, | ||
122 | + Animation<double> secondaryAnimation) { | ||
123 | + final Widget pageChild = child; // ?? Builder(builder: builder); | ||
124 | + return SafeArea( | ||
125 | + child: Builder(builder: (BuildContext context) { | ||
126 | + return theme != null | ||
127 | + ? Theme(data: theme, child: pageChild) | ||
128 | + : pageChild; | ||
129 | + }), | ||
130 | + ); | ||
131 | + }, | ||
132 | + barrierDismissible: barrierDismissible, | ||
133 | + barrierLabel: MaterialLocalizations.of(Get.key.currentContext) | ||
134 | + .modalBarrierDismissLabel, | ||
135 | + barrierColor: Colors.black54, | ||
136 | + transitionDuration: const Duration(milliseconds: 150), | ||
137 | + // transitionBuilder: _buildMaterialDialogTransitions, | ||
138 | + useRootNavigator: useRootNavigator, | ||
139 | + ); | ||
95 | } | 140 | } |
96 | 141 | ||
97 | static defaultDialog( | 142 | static defaultDialog( |
98 | {Color color, | 143 | {Color color, |
99 | - double opacity = 0.5, | 144 | + double opacity = 0.2, |
100 | String title = "Alert dialog", | 145 | String title = "Alert dialog", |
101 | Widget content, | 146 | Widget content, |
102 | Widget cancel, | 147 | Widget cancel, |
103 | Widget confirm}) { | 148 | Widget confirm}) { |
104 | - Get.to(DefaultDialogGet( | 149 | + final child = DefaultDialogGet( |
105 | color: color, | 150 | color: color, |
106 | opacity: opacity, | 151 | opacity: opacity, |
107 | title: title, | 152 | title: title, |
108 | content: content, | 153 | content: content, |
109 | cancel: cancel, | 154 | cancel: cancel, |
110 | confirm: confirm, | 155 | confirm: confirm, |
156 | + ); | ||
157 | + | ||
158 | + dialog(child); | ||
159 | + } | ||
160 | + | ||
161 | + static Future<T> bottomSheet<T>({ | ||
162 | + @required WidgetBuilder builder, | ||
163 | + Color backgroundColor, | ||
164 | + double elevation, | ||
165 | + ShapeBorder shape, | ||
166 | + Clip clipBehavior, | ||
167 | + Color barrierColor, | ||
168 | + bool isScrollControlled = false, | ||
169 | + bool useRootNavigator = false, | ||
170 | + bool isDismissible = true, | ||
171 | + bool enableDrag = true, | ||
172 | + }) { | ||
173 | + assert(builder != null); | ||
174 | + assert(isScrollControlled != null); | ||
175 | + assert(useRootNavigator != null); | ||
176 | + assert(isDismissible != null); | ||
177 | + assert(enableDrag != null); | ||
178 | + | ||
179 | + return Get.key.currentState.push<T>(GetModalBottomSheetRoute<T>( | ||
180 | + builder: builder, | ||
181 | + theme: Theme.of(Get.key.currentContext, shadowThemeOnly: true), | ||
182 | + isScrollControlled: isScrollControlled, | ||
183 | + barrierLabel: MaterialLocalizations.of(Get.key.currentContext) | ||
184 | + .modalBarrierDismissLabel, | ||
185 | + backgroundColor: backgroundColor, | ||
186 | + elevation: elevation, | ||
187 | + shape: shape, | ||
188 | + clipBehavior: clipBehavior, | ||
189 | + isDismissible: isDismissible, | ||
190 | + modalBarrierColor: barrierColor, | ||
191 | + enableDrag: enableDrag, | ||
111 | )); | 192 | )); |
112 | } | 193 | } |
113 | 194 | ||
114 | - /// It replaces Navigator.pushAndRemoveUntil, but needs no context | ||
115 | - static offAll(Widget page, RoutePredicate predicate, | ||
116 | - {bool rebuildRoutes = false}) { | ||
117 | - return key.currentState.pushAndRemoveUntil( | ||
118 | - GetRoute(opaque: rebuildRoutes, builder: (_) => page), predicate); | 195 | + static snackbar(title, message, |
196 | + {Color colorText, Duration duration, SnackPosition snackPosition}) { | ||
197 | + return GetBar( | ||
198 | + titleText: Text( | ||
199 | + title, | ||
200 | + style: TextStyle( | ||
201 | + color: colorText ?? Theme.of(Get.key.currentContext).accentColor, | ||
202 | + fontWeight: FontWeight.w800, | ||
203 | + fontSize: 16), | ||
204 | + ), | ||
205 | + messageText: Text( | ||
206 | + message, | ||
207 | + style: TextStyle( | ||
208 | + color: colorText ?? Theme.of(Get.key.currentContext).accentColor, | ||
209 | + fontWeight: FontWeight.w300, | ||
210 | + fontSize: 14), | ||
211 | + ), | ||
212 | + snackPosition: snackPosition ?? SnackPosition.TOP, | ||
213 | + borderRadius: 15, | ||
214 | + margin: EdgeInsets.symmetric(horizontal: 10), | ||
215 | + duration: duration ?? Duration(seconds: 3), | ||
216 | + barBlur: 7.0, | ||
217 | + backgroundColor: Colors.grey.withOpacity(0.2), | ||
218 | + )..show(); | ||
119 | } | 219 | } |
120 | } | 220 | } |
@@ -2,7 +2,7 @@ import 'dart:async'; | @@ -2,7 +2,7 @@ import 'dart:async'; | ||
2 | import 'dart:ui'; | 2 | import 'dart:ui'; |
3 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
4 | import 'package:flutter/scheduler.dart'; | 4 | import 'package:flutter/scheduler.dart'; |
5 | -import 'package:get/get.dart'; | 5 | +import 'routes.dart'; |
6 | import 'snack_route.dart' as route; | 6 | import 'snack_route.dart' as route; |
7 | 7 | ||
8 | typedef void SnackStatusCallback(SnackStatus status); | 8 | typedef void SnackStatusCallback(SnackStatus status); |
@@ -216,7 +216,6 @@ class GetBar<T extends Object> extends StatefulWidget { | @@ -216,7 +216,6 @@ class GetBar<T extends Object> extends StatefulWidget { | ||
216 | _snackRoute = route.showSnack<T>( | 216 | _snackRoute = route.showSnack<T>( |
217 | snack: this, | 217 | snack: this, |
218 | ); | 218 | ); |
219 | - | ||
220 | return await Get.key.currentState.push(_snackRoute); | 219 | return await Get.key.currentState.push(_snackRoute); |
221 | } | 220 | } |
222 | 221 |
1 | name: get | 1 | name: get |
2 | description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars with no context. | 2 | description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars with no context. |
3 | -version: 1.6.3 | ||
4 | -author: Jonny Borges <jonataborges01@gmail.com> | 3 | +version: 1.7.1 |
5 | homepage: https://github.com/jonataslaw/get | 4 | homepage: https://github.com/jonataslaw/get |
6 | 5 | ||
7 | environment: | 6 | environment: |
-
Please register or login to post a comment