Jonny Borges
Committed by GitHub

Merge pull request #891 from SchabanBo/master

Fixs for #888 #889
@@ -53,6 +53,8 @@ @@ -53,6 +53,8 @@
53 - [ObxValue](#obxvalue) 53 - [ObxValue](#obxvalue)
54 - [Useful tips](#useful-tips) 54 - [Useful tips](#useful-tips)
55 - [GetView](#getview) 55 - [GetView](#getview)
  56 + - [GetResponsiveView](#getresponsiveview)
  57 + - [How to use it](#how-to-use-it)
56 - [GetWidget](#getwidget) 58 - [GetWidget](#getwidget)
57 - [GetxService](#getxservice) 59 - [GetxService](#getxservice)
58 - [Breaking changes from 2.0](#breaking-changes-from-20) 60 - [Breaking changes from 2.0](#breaking-changes-from-20)
@@ -903,6 +905,29 @@ Is a `const Stateless` Widget that has a getter `controller` for a registered `C @@ -903,6 +905,29 @@ Is a `const Stateless` Widget that has a getter `controller` for a registered `C
903 } 905 }
904 ``` 906 ```
905 907
  908 +#### GetResponsiveView
  909 +
  910 +Extend this widget to build responsive view.
  911 +this widget contains the `screen` property that have all
  912 +information about the screen size and type.
  913 +
  914 +##### How to use it
  915 +
  916 +You have two options to build it.
  917 +
  918 +- with `builder` method you return the widget to build.
  919 +- with methods `desktop`, `tablet`,`phone`, `watch`. the specific
  920 +method will be built when the screen type matches the method
  921 +when the screen is [ScreenType.Tablet] the `tablet` method
  922 +will be exuded and so on.
  923 +**Note:** If you use this method please set the property `alwaysUseBuilder` to `false`
  924 +
  925 +With `settings` property you can set the width limit for the screen types.
  926 +
  927 +![example](https://github.com/SchabanBo/get_page_example/blob/master/docs/Example.gif?raw=true)
  928 +Code to this screen
  929 +[code](https://github.com/SchabanBo/get_page_example/blob/master/lib/pages/responsive_example/responsive_view.dart)
  930 +
906 #### GetWidget 931 #### GetWidget
907 932
908 Most people have no idea about this Widget, or totally confuse the usage of it. 933 Most people have no idea about this Widget, or totally confuse the usage of it.
@@ -191,54 +191,11 @@ class GetCupertinoApp extends StatelessWidget { @@ -191,54 +191,11 @@ class GetCupertinoApp extends StatelessWidget {
191 return PageRedirect(settings, unknownRoute).page(); 191 return PageRedirect(settings, unknownRoute).page();
192 } 192 }
193 193
194 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
195 - final match = Get.routeTree.matchRoute(name);  
196 - Get.parameters = match?.parameters;  
197 -  
198 - //Route can be nullable, just pass the unknown route  
199 - if (match?.route == null) {  
200 - return [  
201 - GetPageRoute(  
202 - page: unknownRoute.page,  
203 - parameter: unknownRoute.parameter,  
204 - settings: RouteSettings(name: name, arguments: null),  
205 - curve: unknownRoute.curve,  
206 - opaque: unknownRoute.opaque,  
207 - routeName: unknownRoute.name,  
208 - customTransition: unknownRoute.customTransition,  
209 - binding: unknownRoute.binding,  
210 - bindings: unknownRoute.bindings,  
211 - transitionDuration: (unknownRoute.transitionDuration ??  
212 - Get.defaultTransitionDuration),  
213 - transition: unknownRoute.transition,  
214 - popGesture: unknownRoute.popGesture,  
215 - fullscreenDialog: unknownRoute.fullscreenDialog,  
216 - )  
217 - ];  
218 - }  
219 -  
220 - return [  
221 - GetPageRoute(  
222 - page: match.route.page,  
223 - parameter: match.route.parameter,  
224 - settings: RouteSettings(name: name, arguments: null),  
225 - curve: match.route.curve,  
226 - opaque: match.route.opaque,  
227 - routeName: match.route.name,  
228 - binding: match.route.binding,  
229 - bindings: match.route.bindings,  
230 - transitionDuration:  
231 - (match.route.transitionDuration ?? Get.defaultTransitionDuration),  
232 - transition: match.route.transition,  
233 - popGesture: match.route.popGesture,  
234 - fullscreenDialog: match.route.fullscreenDialog,  
235 - )  
236 - ];  
237 - } 194 + List<Route<dynamic>> initialRoutesGenerate(String name) =>
  195 + [PageRedirect(RouteSettings(name: name), unknownRoute).page()];
238 196
239 @override 197 @override
240 - Widget build(BuildContext context) {  
241 - return GetBuilder<GetMaterialController>( 198 + Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
242 init: Get.rootController, 199 init: Get.rootController,
243 dispose: (d) { 200 dispose: (d) {
244 onDispose?.call(); 201 onDispose?.call();
@@ -274,8 +231,41 @@ class GetCupertinoApp extends StatelessWidget { @@ -274,8 +231,41 @@ class GetCupertinoApp extends StatelessWidget {
274 transitionDuration ?? Get.defaultTransitionDuration, 231 transitionDuration ?? Get.defaultTransitionDuration,
275 ); 232 );
276 }, 233 },
277 - builder: (_) {  
278 - return CupertinoApp( 234 + builder: (_) => routerDelegate != null
  235 + ? CupertinoApp.router(
  236 + routerDelegate: routerDelegate,
  237 + routeInformationParser: routeInformationParser,
  238 + backButtonDispatcher: backButtonDispatcher,
  239 + routeInformationProvider: routeInformationProvider,
  240 + key: _.unikey,
  241 + theme: theme,
  242 + builder: (context, child) {
  243 + return Directionality(
  244 + textDirection: textDirection ??
  245 + (rtlLanguages.contains(Get.locale?.languageCode)
  246 + ? TextDirection.rtl
  247 + : TextDirection.ltr),
  248 + child: builder == null ? child : builder(context, child),
  249 + );
  250 + },
  251 + title: title ?? '',
  252 + onGenerateTitle: onGenerateTitle,
  253 + color: color,
  254 + locale: Get.locale ?? locale,
  255 + localizationsDelegates: localizationsDelegates,
  256 + localeListResolutionCallback: localeListResolutionCallback,
  257 + localeResolutionCallback: localeResolutionCallback,
  258 + supportedLocales:
  259 + supportedLocales ?? const <Locale>[Locale('en', 'US')],
  260 + showPerformanceOverlay: showPerformanceOverlay ?? false,
  261 + checkerboardRasterCacheImages:
  262 + checkerboardRasterCacheImages ?? false,
  263 + checkerboardOffscreenLayers: checkerboardOffscreenLayers ?? false,
  264 + showSemanticsDebugger: showSemanticsDebugger ?? false,
  265 + debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
  266 + shortcuts: shortcuts,
  267 + )
  268 + : CupertinoApp(
279 key: _.unikey, 269 key: _.unikey,
280 theme: theme, 270 theme: theme,
281 navigatorKey: 271 navigatorKey:
@@ -289,8 +279,12 @@ class GetCupertinoApp extends StatelessWidget { @@ -289,8 +279,12 @@ class GetCupertinoApp extends StatelessWidget {
289 : initialRoutesGenerate, 279 : initialRoutesGenerate,
290 onUnknownRoute: onUnknownRoute, 280 onUnknownRoute: onUnknownRoute,
291 navigatorObservers: (navigatorObservers == null 281 navigatorObservers: (navigatorObservers == null
292 - ? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]  
293 - : <NavigatorObserver>[GetObserver(routingCallback, Get.routing)] 282 + ? <NavigatorObserver>[
  283 + GetObserver(routingCallback, Get.routing)
  284 + ]
  285 + : <NavigatorObserver>[
  286 + GetObserver(routingCallback, Get.routing)
  287 + ]
294 ..addAll(navigatorObservers)), 288 ..addAll(navigatorObservers)),
295 builder: (context, child) { 289 builder: (context, child) {
296 return Directionality( 290 return Directionality(
@@ -304,7 +298,6 @@ class GetCupertinoApp extends StatelessWidget { @@ -304,7 +298,6 @@ class GetCupertinoApp extends StatelessWidget {
304 title: title ?? '', 298 title: title ?? '',
305 onGenerateTitle: onGenerateTitle, 299 onGenerateTitle: onGenerateTitle,
306 color: color, 300 color: color,
307 -  
308 locale: Get.locale ?? locale, 301 locale: Get.locale ?? locale,
309 localizationsDelegates: localizationsDelegates, 302 localizationsDelegates: localizationsDelegates,
310 localeListResolutionCallback: localeListResolutionCallback, 303 localeListResolutionCallback: localeListResolutionCallback,
@@ -319,7 +312,5 @@ class GetCupertinoApp extends StatelessWidget { @@ -319,7 +312,5 @@ class GetCupertinoApp extends StatelessWidget {
319 debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true, 312 debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
320 shortcuts: shortcuts, 313 shortcuts: shortcuts,
321 // actions: actions, 314 // actions: actions,
322 - );  
323 - });  
324 - } 315 + ));
325 } 316 }
@@ -198,58 +198,14 @@ class GetMaterialApp extends StatelessWidget { @@ -198,58 +198,14 @@ class GetMaterialApp extends StatelessWidget {
198 initialRoute = null, 198 initialRoute = null,
199 super(key: key); 199 super(key: key);
200 200
201 - Route<dynamic> generator(RouteSettings settings) {  
202 - return PageRedirect(settings, unknownRoute).page();  
203 - }  
204 -  
205 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
206 - final match = Get.routeTree.matchRoute(name);  
207 - Get.parameters = match?.parameters; 201 + Route<dynamic> generator(RouteSettings settings) =>
  202 + PageRedirect(settings, unknownRoute).page();
208 203
209 - //Route can be nullable, just pass the unknown route  
210 - if (match?.route == null) {  
211 - return [  
212 - GetPageRoute(  
213 - page: unknownRoute.page,  
214 - parameter: unknownRoute.parameter,  
215 - settings: RouteSettings(name: name, arguments: null),  
216 - curve: unknownRoute.curve,  
217 - opaque: unknownRoute.opaque,  
218 - routeName: unknownRoute.name,  
219 - customTransition: unknownRoute.customTransition,  
220 - binding: unknownRoute.binding,  
221 - bindings: unknownRoute.bindings,  
222 - transitionDuration: (unknownRoute.transitionDuration ??  
223 - Get.defaultTransitionDuration),  
224 - transition: unknownRoute.transition,  
225 - popGesture: unknownRoute.popGesture,  
226 - fullscreenDialog: unknownRoute.fullscreenDialog,  
227 - )  
228 - ];  
229 - }  
230 -  
231 - return [  
232 - GetPageRoute(  
233 - page: match.route.page,  
234 - parameter: match.route.parameter,  
235 - settings: RouteSettings(name: name, arguments: null),  
236 - curve: match.route.curve,  
237 - opaque: match.route.opaque,  
238 - binding: match.route.binding,  
239 - routeName: match.route.name,  
240 - bindings: match.route.bindings,  
241 - transitionDuration:  
242 - (match.route.transitionDuration ?? Get.defaultTransitionDuration),  
243 - transition: match.route.transition,  
244 - popGesture: match.route.popGesture,  
245 - fullscreenDialog: match.route.fullscreenDialog,  
246 - )  
247 - ];  
248 - } 204 + List<Route<dynamic>> initialRoutesGenerate(String name) =>
  205 + [PageRedirect(RouteSettings(name: name), unknownRoute).page()];
249 206
250 @override 207 @override
251 - Widget build(BuildContext context) {  
252 - return GetBuilder<GetMaterialController>( 208 + Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
253 init: Get.rootController, 209 init: Get.rootController,
254 dispose: (d) { 210 dispose: (d) {
255 onDispose?.call(); 211 onDispose?.call();
@@ -285,8 +241,44 @@ class GetMaterialApp extends StatelessWidget { @@ -285,8 +241,44 @@ class GetMaterialApp extends StatelessWidget {
285 transitionDuration ?? Get.defaultTransitionDuration, 241 transitionDuration ?? Get.defaultTransitionDuration,
286 ); 242 );
287 }, 243 },
288 - builder: (_) {  
289 - return MaterialApp( 244 + builder: (_) => routerDelegate != null
  245 + ? MaterialApp.router(
  246 + routerDelegate: routerDelegate,
  247 + routeInformationParser: routeInformationParser,
  248 + backButtonDispatcher: backButtonDispatcher,
  249 + routeInformationProvider: routeInformationProvider,
  250 + key: _.unikey,
  251 + builder: (context, child) {
  252 + return Directionality(
  253 + textDirection: textDirection ??
  254 + (rtlLanguages.contains(Get.locale?.languageCode)
  255 + ? TextDirection.rtl
  256 + : TextDirection.ltr),
  257 + child: builder == null ? child : builder(context, child),
  258 + );
  259 + },
  260 + title: title ?? '',
  261 + onGenerateTitle: onGenerateTitle,
  262 + color: color,
  263 + theme: _.theme ?? theme ?? ThemeData.fallback(),
  264 + darkTheme: darkTheme,
  265 + themeMode: _.themeMode ?? themeMode ?? ThemeMode.system,
  266 + locale: Get.locale ?? locale,
  267 + localizationsDelegates: localizationsDelegates,
  268 + localeListResolutionCallback: localeListResolutionCallback,
  269 + localeResolutionCallback: localeResolutionCallback,
  270 + supportedLocales:
  271 + supportedLocales ?? const <Locale>[Locale('en', 'US')],
  272 + debugShowMaterialGrid: debugShowMaterialGrid ?? false,
  273 + showPerformanceOverlay: showPerformanceOverlay ?? false,
  274 + checkerboardRasterCacheImages:
  275 + checkerboardRasterCacheImages ?? false,
  276 + checkerboardOffscreenLayers: checkerboardOffscreenLayers ?? false,
  277 + showSemanticsDebugger: showSemanticsDebugger ?? false,
  278 + debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
  279 + shortcuts: shortcuts,
  280 + )
  281 + : MaterialApp(
290 key: _.unikey, 282 key: _.unikey,
291 navigatorKey: 283 navigatorKey:
292 (navigatorKey == null ? Get.key : Get.addKey(navigatorKey)), 284 (navigatorKey == null ? Get.key : Get.addKey(navigatorKey)),
@@ -299,8 +291,12 @@ class GetMaterialApp extends StatelessWidget { @@ -299,8 +291,12 @@ class GetMaterialApp extends StatelessWidget {
299 : initialRoutesGenerate, 291 : initialRoutesGenerate,
300 onUnknownRoute: onUnknownRoute, 292 onUnknownRoute: onUnknownRoute,
301 navigatorObservers: (navigatorObservers == null 293 navigatorObservers: (navigatorObservers == null
302 - ? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]  
303 - : <NavigatorObserver>[GetObserver(routingCallback, Get.routing)] 294 + ? <NavigatorObserver>[
  295 + GetObserver(routingCallback, Get.routing)
  296 + ]
  297 + : <NavigatorObserver>[
  298 + GetObserver(routingCallback, Get.routing)
  299 + ]
304 ..addAll(navigatorObservers)), 300 ..addAll(navigatorObservers)),
305 builder: (context, child) { 301 builder: (context, child) {
306 return Directionality( 302 return Directionality(
@@ -332,7 +328,5 @@ class GetMaterialApp extends StatelessWidget { @@ -332,7 +328,5 @@ class GetMaterialApp extends StatelessWidget {
332 debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true, 328 debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
333 shortcuts: shortcuts, 329 shortcuts: shortcuts,
334 // actions: actions, 330 // actions: actions,
335 - );  
336 - });  
337 - } 331 + ));
338 } 332 }
@@ -5,6 +5,7 @@ export 'src/rx_flutter/rx_getx_widget.dart'; @@ -5,6 +5,7 @@ export 'src/rx_flutter/rx_getx_widget.dart';
5 export 'src/rx_flutter/rx_notifier.dart'; 5 export 'src/rx_flutter/rx_notifier.dart';
6 export 'src/rx_flutter/rx_obx_widget.dart'; 6 export 'src/rx_flutter/rx_obx_widget.dart';
7 export 'src/rx_flutter/rx_ticket_provider_mixin.dart'; 7 export 'src/rx_flutter/rx_ticket_provider_mixin.dart';
  8 +export 'src/simple/get_responsive.dart';
8 export 'src/simple/get_state.dart'; 9 export 'src/simple/get_state.dart';
9 export 'src/simple/get_view.dart'; 10 export 'src/simple/get_view.dart';
10 export 'src/simple/immutable_state.dart'; 11 export 'src/simple/immutable_state.dart';
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +import '../../../get.dart';
  4 +import 'get_view.dart';
  5 +
  6 +abstract class _GetResponsive<T> extends GetView<T> {
  7 + final ResponsiveScreen screen;
  8 + _GetResponsive(ResponsiveScreenSettings settings, {Key key})
  9 + : screen = ResponsiveScreen(settings),
  10 + super(key: key);
  11 +
  12 + Widget builder();
  13 + Widget phone();
  14 + Widget tablet();
  15 + Widget desktop();
  16 + Widget watch();
  17 +}
  18 +
  19 +/// Extend this widget to build responsive view.
  20 +/// this widget contains the `screen` property that have all
  21 +/// information about the screen size and type.
  22 +/// You have two options to build it.
  23 +/// 1- with `builder` method you return the widget to build.
  24 +/// 2- with methods `desktop`, `tablet`,`phone`, `watch`. the specific
  25 +/// method will be built when the screen type matches the method
  26 +/// when the screen is [ScreenType.Tablet] the `tablet` method
  27 +/// will be exuded and so on.
  28 +/// Note if you use this method please set the
  29 +/// property `alwaysUseBuilder` to false
  30 +/// With `settings` property you can set the width limit for the screen types.
  31 +class GetResponsiveView<T> extends _GetResponsive<T> {
  32 + final bool alwaysUseBuilder = true;
  33 + GetResponsiveView(
  34 + {alwaysUseBuilder,
  35 + ResponsiveScreenSettings settings = const ResponsiveScreenSettings(),
  36 + Key key})
  37 + : super(settings, key: key);
  38 + @override
  39 + Widget build(BuildContext context) {
  40 + screen.context = context;
  41 + Widget widget;
  42 + if (alwaysUseBuilder) {
  43 + widget = builder();
  44 + if (widget != null) return widget;
  45 + }
  46 + if (screen.isDesktop) {
  47 + widget = desktop() ?? widget;
  48 + if (widget != null) return widget;
  49 + }
  50 + if (screen.isTablet) {
  51 + widget = tablet() ?? desktop();
  52 + if (widget != null) return widget;
  53 + }
  54 + if (screen.isPhone) {
  55 + widget = phone() ?? tablet() ?? desktop();
  56 + if (widget != null) return widget;
  57 + }
  58 + return watch() ?? phone() ?? tablet() ?? desktop() ?? builder();
  59 + }
  60 +
  61 + @override
  62 + Widget builder() => null;
  63 +
  64 + @override
  65 + Widget desktop() => null;
  66 +
  67 + @override
  68 + Widget phone() => null;
  69 +
  70 + @override
  71 + Widget tablet() => null;
  72 +
  73 + @override
  74 + Widget watch() => null;
  75 +}
  76 +
  77 +class ResponsiveScreenSettings {
  78 + /// When the width is greater als this value
  79 + /// the display will be set as [ScreenType.Desktop]
  80 + final double desktopChangePoint;
  81 +
  82 + /// When the width is greater als this value
  83 + /// the display will be set as [ScreenType.Tablet]
  84 + /// or when width greater als [watchChangePoint] and smaller als this value
  85 + /// the display will be [ScreenType.Mobile]
  86 + final double tabletChangePoint;
  87 +
  88 + /// When the width is smaller als this value
  89 + /// the display will be set as [ScreenType.Watch]
  90 + /// or when width greater als this value and smaller als [tabletChangePoint]
  91 + /// the display will be [ScreenType.Mobile]
  92 + final double watchChangePoint;
  93 +
  94 + const ResponsiveScreenSettings(
  95 + {this.desktopChangePoint = 1200,
  96 + this.tabletChangePoint = 600,
  97 + this.watchChangePoint = 300});
  98 +}
  99 +
  100 +class ResponsiveScreen {
  101 + BuildContext context;
  102 + final ResponsiveScreenSettings settings;
  103 +
  104 + bool _isPaltformDesktop;
  105 + ResponsiveScreen(this.settings) {
  106 + _isPaltformDesktop = GetPlatform.isDesktop;
  107 + }
  108 +
  109 + double get height => context.height;
  110 + double get width => context.width;
  111 +
  112 + /// Is [screenType] [ScreenType.Desktop]
  113 + bool get isDesktop => (screenType == ScreenType.Desktop);
  114 +
  115 + /// Is [screenType] [ScreenType.Tablet]
  116 + bool get isTablet => (screenType == ScreenType.Tablet);
  117 +
  118 + /// Is [screenType] [ScreenType.Mobile]
  119 + bool get isPhone => (screenType == ScreenType.Phone);
  120 +
  121 + /// Is [screenType] [ScreenType.Watch]
  122 + bool get isWatch => (screenType == ScreenType.Watch);
  123 +
  124 + double get _getdeviceWidth {
  125 + if (_isPaltformDesktop) {
  126 + return width;
  127 + }
  128 + return context.mediaQueryShortestSide;
  129 + }
  130 +
  131 + ScreenType get screenType {
  132 + final deviceWidth = _getdeviceWidth;
  133 + if (deviceWidth >= settings.desktopChangePoint) return ScreenType.Desktop;
  134 + if (deviceWidth >= settings.tabletChangePoint) return ScreenType.Tablet;
  135 + if (deviceWidth < settings.watchChangePoint) return ScreenType.Watch;
  136 + return ScreenType.Phone;
  137 + }
  138 +
  139 + /// Return widget according to screen type
  140 + /// if the [screenType] is [ScreenType.Desktop] and
  141 + /// `desktop` object is null the `tablet` object will be returned
  142 + /// and if `tablet` object is null the `mobile` object will be returned
  143 + /// and if `mobile` object is null the `watch` object will be returned
  144 + /// also when it is null.
  145 + T responsiveValue<T>({
  146 + T mobile,
  147 + T tablet,
  148 + T desktop,
  149 + T watch,
  150 + }) {
  151 + if (isDesktop && desktop != null) return desktop;
  152 + if (isTablet && tablet != null) return tablet;
  153 + if (isPhone && mobile != null) return mobile;
  154 + return watch;
  155 + }
  156 +}
  157 +
  158 +enum ScreenType {
  159 + Watch,
  160 + Phone,
  161 + Tablet,
  162 + Desktop,
  163 +}