Showing
9 changed files
with
649 additions
and
122 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. |
@@ -84,4 +84,22 @@ | @@ -84,4 +84,22 @@ | ||
84 | 84 | ||
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,24 +102,22 @@ To open default dialog: | @@ -91,24 +102,22 @@ 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 | - | ||
106 | 120 | ||
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 | 121 | ||
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 | ||
@@ -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( | ||
55 | - title: Text(title, textAlign: TextAlign.center), | ||
56 | - content: content, | ||
57 | - actions: <Widget>[cancel, confirm], | ||
58 | - ), | ||
59 | - ), | ||
60 | - ), | 24 | + return AlertDialog( |
25 | + title: Text(title, textAlign: TextAlign.center), | ||
26 | + content: content, | ||
27 | + actions: <Widget>[cancel, confirm], | ||
28 | + ); | ||
29 | + } | ||
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, | ||
61 | ); | 99 | ); |
62 | } | 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 | + } | ||
63 | } | 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