get_responsive.dart
4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import 'package:flutter/widgets.dart';
import '../../../get.dart';
mixin GetResponsiveMixin on Widget {
ResponsiveScreen get screen;
bool get alwaysUseBuilder;
@protected
Widget build(BuildContext context) {
screen.context = context;
Widget? widget;
if (alwaysUseBuilder) {
widget = builder();
if (widget != null) return widget;
}
if (screen.isDesktop) {
widget = desktop() ?? widget;
if (widget != null) return widget;
}
if (screen.isTablet) {
widget = tablet() ?? desktop();
if (widget != null) return widget;
}
if (screen.isPhone) {
widget = phone() ?? tablet() ?? desktop();
if (widget != null) return widget;
}
return watch() ?? phone() ?? tablet() ?? desktop() ?? builder()!;
}
Widget? builder() => null;
Widget? desktop() => null;
Widget? phone() => null;
Widget? tablet() => null;
Widget? watch() => null;
}
/// Extend this widget to build responsive view.
/// this widget contains the `screen` property that have all
/// information about the screen size and type.
/// You have two options to build it.
/// 1- with `builder` method you return the widget to build.
/// 2- with methods `desktop`, `tablet`,`phone`, `watch`. the specific
/// method will be built when the screen type matches the method
/// when the screen is [ScreenType.Tablet] the `tablet` method
/// will be exuded and so on.
/// Note if you use this method please set the
/// property `alwaysUseBuilder` to false
/// With `settings` property you can set the width limit for the screen types.
class GetResponsiveView<T> extends GetView<T> with GetResponsiveMixin {
@override
final bool alwaysUseBuilder;
@override
final ResponsiveScreen screen;
GetResponsiveView({
this.alwaysUseBuilder = false,
ResponsiveScreenSettings settings = const ResponsiveScreenSettings(),
Key? key,
}) : screen = ResponsiveScreen(settings),
super(key: key);
}
class GetResponsiveWidget<T extends GetLifeCycleMixin> extends GetWidget<T>
with GetResponsiveMixin {
@override
final bool alwaysUseBuilder;
@override
final ResponsiveScreen screen;
GetResponsiveWidget({
this.alwaysUseBuilder = false,
ResponsiveScreenSettings settings = const ResponsiveScreenSettings(),
Key? key,
}) : screen = ResponsiveScreen(settings),
super(key: key);
}
class ResponsiveScreenSettings {
/// When the width is greater als this value
/// the display will be set as [ScreenType.Desktop]
final double desktopChangePoint;
/// When the width is greater als this value
/// the display will be set as [ScreenType.Tablet]
/// or when width greater als [watchChangePoint] and smaller als this value
/// the display will be [ScreenType.Phone]
final double tabletChangePoint;
/// When the width is smaller als this value
/// the display will be set as [ScreenType.Watch]
/// or when width greater als this value and smaller als [tabletChangePoint]
/// the display will be [ScreenType.Phone]
final double watchChangePoint;
const ResponsiveScreenSettings(
{this.desktopChangePoint = 1200,
this.tabletChangePoint = 600,
this.watchChangePoint = 300});
}
class ResponsiveScreen {
late BuildContext context;
final ResponsiveScreenSettings settings;
late bool _isPlatformDesktop;
ResponsiveScreen(this.settings) {
_isPlatformDesktop = GetPlatform.isDesktop;
}
double get height => context.height;
double get width => context.width;
/// Is [screenType] [ScreenType.Desktop]
bool get isDesktop => (screenType == ScreenType.desktop);
/// Is [screenType] [ScreenType.Tablet]
bool get isTablet => (screenType == ScreenType.tablet);
/// Is [screenType] [ScreenType.Phone]
bool get isPhone => (screenType == ScreenType.phone);
/// Is [screenType] [ScreenType.Watch]
bool get isWatch => (screenType == ScreenType.watch);
double get _getDeviceWidth {
if (_isPlatformDesktop) {
return width;
}
return context.mediaQueryShortestSide;
}
ScreenType get screenType {
final deviceWidth = _getDeviceWidth;
if (deviceWidth >= settings.desktopChangePoint) return ScreenType.desktop;
if (deviceWidth >= settings.tabletChangePoint) return ScreenType.tablet;
if (deviceWidth < settings.watchChangePoint) return ScreenType.watch;
return ScreenType.phone;
}
/// Return widget according to screen type
/// if the [screenType] is [ScreenType.Desktop] and
/// `desktop` object is null the `tablet` object will be returned
/// and if `tablet` object is null the `mobile` object will be returned
/// and if `mobile` object is null the `watch` object will be returned
/// also when it is null.
T? responsiveValue<T>({
T? mobile,
T? tablet,
T? desktop,
T? watch,
}) {
if (isDesktop && desktop != null) return desktop;
if (isTablet && tablet != null) return tablet;
if (isPhone && mobile != null) return mobile;
return watch;
}
}
enum ScreenType {
watch,
phone,
tablet,
desktop,
}