Committed by
GitHub
Major updates & fixes (#491)
* Clean codes & add features & fix bugs Features/Bugs: - Feature: You can select what classes needs to be rebuilt instead of rebuilding everything, if you have widget A, either addi SU mixin or add 'A' to list ScreenUtilInit.responsiveWidgets - Feature: Using ScreenUtilInit.builder is optional (use it only when using library in theme) - Bug: Second call to ScreenUtil.init ignores any existing values and uses the default values when not provided, use ScreenUtil.configure instead - Bug: ScreenUtil.ensureScreenSize raises an overflow error * Update version * Add List of flutter widgets * Update logic if allowing widget to being rebuilt * Little code solidity * Add scale factors: diagonal & diameter * Add option for how font size should be scaled * Update support to Dart >= 2.17.0 * Add fontSizeResolver to init + helpers * Add ensureScreenSize to ScreenUtilInit constructor * Fix ensureScreenSize on web * Update Runner.rc * Add some methods to extensions * Update widget_test * Remove extra deps * Clean code * Add ensureScreenSizeAndInit + make init sync * Update README.md * Update CHANGELOG.md * Update version to 5.9.0 * Rename version * Adding tests * Changing version in CHANGELOG.md --------- Co-authored-by: Mounir Bouaiche <mounir-b@dba.ma>
Showing
19 changed files
with
1328 additions
and
192 deletions
1 | +# 5.9.0-beta | ||
2 | +- ScreenUtilInit won't rebuild the whole widget tree | ||
3 | +- Add `fontSizeResolver` to specify how font size should be scaled | ||
4 | +- Add `diameter` & `diagonal` factors | ||
5 | +- `useInheritedMediaQuery` has not effect, and will be removed in next release | ||
6 | +- Fix `ensureScreenSize` in web platform | ||
7 | + | ||
1 | # 5.8.4 | 8 | # 5.8.4 |
2 | - bug fix | 9 | - bug fix |
3 | - change useInheritedMediaQuery default value to false | 10 | - change useInheritedMediaQuery default value to false |
@@ -38,28 +38,36 @@ dependencies: | @@ -38,28 +38,36 @@ dependencies: | ||
38 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 38 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
39 | ``` | 39 | ``` |
40 | 40 | ||
41 | -### Property | 41 | +### Properties |
42 | 42 | ||
43 | | Property | Type | Default Value | Description | | 43 | | Property | Type | Default Value | Description | |
44 | -| --------------- |--------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------| | ||
45 | -| deviceSize | Size | null | The size of the physical device | | 44 | +| ---------------- |--------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------| |
46 | | designSize | Size | Size(360,690) | The size of the device screen in the design draft, in dp | | 45 | | designSize | Size | Size(360,690) | The size of the device screen in the design draft, in dp | |
47 | | builder | Function | null | Return widget that uses the library in a property (ex: MaterialApp's theme) | | 46 | | builder | Function | null | Return widget that uses the library in a property (ex: MaterialApp's theme) | |
48 | | child | Widget | null | A part of builder that its dependencies/properties don't use the library | | 47 | | child | Widget | null | A part of builder that its dependencies/properties don't use the library | |
49 | -| rebuildFactor | Function | *default* | Returns whether to rebuild or not when screen metrics changes. | | ||
50 | -| orientation | Orientation | portrait | screen orientation | | 48 | +| rebuildFactor | Function | *default* | Function that take old and new screen metrics and returns whether to rebuild or not when changes. | |
51 | | splitScreenMode | bool | false | support for split screen | | 49 | | splitScreenMode | bool | false | support for split screen | |
52 | | minTextAdapt | bool | false | Whether to adapt the text according to the minimum of width and height | | 50 | | minTextAdapt | bool | false | Whether to adapt the text according to the minimum of width and height | |
53 | | context | BuildContext | null | Get physical device data if not provided, by MediaQuery.of(context) | | 51 | | context | BuildContext | null | Get physical device data if not provided, by MediaQuery.of(context) | |
54 | -| useInheritedMediaQuery | bool | false | Recommended use `false` avoid rebuild very frequently <br/><br/> ~~Set this to true for Flutter 3.10 to avoid keyboard overlay on TextField~~ | | 52 | +| fontSizeResolver | Function | *default* | Function that specify how font size should be adapted. Default is that font size scale with width of screen. | |
53 | +| reponsiveWidgets | Iterable<String> | null | List/Set of widget names that should be included in rebuilding tree. (See [How flutter_screenutil marks a widget needs build](#rebuild-list)) | | ||
55 | 54 | ||
56 | **Note : You must either provide builder, child or both.** | 55 | **Note : You must either provide builder, child or both.** |
57 | 56 | ||
57 | +### Rebuild list | ||
58 | +Starting from version 5.9.0, ScreenUtilInit won't rebuild the whole widget tree, instead it will mark widget needs build only if: | ||
59 | +- Widget is not a flutter widget (widgets are available in [Flutter Docs](https://docs.flutter.dev/reference/widgets)) | ||
60 | +- Widget does not start with underscore (`_`) | ||
61 | +- Widget does not declare `SU` mixin | ||
62 | +- `reponsiveWidgets` does not contains widget name | ||
63 | + | ||
64 | +If you have a widget that uses the library and doesn't meet these options you can either add `SU` mixin or add widget name in responsiveWidgets list. | ||
65 | + | ||
58 | ### Initialize and set the fit size and font size to scale according to the system's "font size" accessibility option | 66 | ### Initialize and set the fit size and font size to scale according to the system's "font size" accessibility option |
59 | 67 | ||
60 | Please set the size of the design draft before use, the width and height of the design draft. | 68 | Please set the size of the design draft before use, the width and height of the design draft. |
61 | 69 | ||
62 | -#### The first way (You must use it once in your app) | 70 | +#### The first way (You should use it once in your app) |
63 | 71 | ||
64 | ```dart | 72 | ```dart |
65 | void main() => runApp(MyApp()); | 73 | void main() => runApp(MyApp()); |
@@ -74,7 +82,8 @@ class MyApp extends StatelessWidget { | @@ -74,7 +82,8 @@ class MyApp extends StatelessWidget { | ||
74 | designSize: const Size(360, 690), | 82 | designSize: const Size(360, 690), |
75 | minTextAdapt: true, | 83 | minTextAdapt: true, |
76 | splitScreenMode: true, | 84 | splitScreenMode: true, |
77 | - builder: (context , child) { | 85 | + // Use builder only if you need to use library outside ScreenUtilInit context |
86 | + builder: (_ , child) { | ||
78 | return MaterialApp( | 87 | return MaterialApp( |
79 | debugShowCheckedModeBanner: false, | 88 | debugShowCheckedModeBanner: false, |
80 | title: 'First Method', | 89 | title: 'First Method', |
@@ -169,6 +178,8 @@ class _HomePageState extends State<HomePage> { | @@ -169,6 +178,8 @@ class _HomePageState extends State<HomePage> { | ||
169 | } | 178 | } |
170 | ``` | 179 | ``` |
171 | 180 | ||
181 | +**Note: calling ScreenUtil.init second time, any non-provided parameter will not be replaced with default value. Use ScreenUtil.configure instead** | ||
182 | + | ||
172 | ### API | 183 | ### API |
173 | 184 | ||
174 | #### Pass the dp size of the design draft | 185 | #### Pass the dp size of the design draft |
example/lib/responsive_widgets.g.dart
0 → 100644
1 | +///////////////////////////////////////////////////////////////////////// | ||
2 | +/// Generated via plugin: flutter_screenutil_generator - Do Not Touch /// | ||
3 | +///////////////////////////////////////////////////////////////////////// | ||
4 | + | ||
5 | +part of 'responsive_widgets.su.dart'; | ||
6 | + | ||
7 | +const _responsiveWidgets = { | ||
8 | + 'MyThemedApp', | ||
9 | + 'MyApp', | ||
10 | + 'HomePageScaffold', | ||
11 | +}; |
example/lib/responsive_widgets.su.dart
0 → 100644
1 | +import 'package:example/responsive_widgets.su.dart'; | ||
1 | import 'package:example/src/home.dart'; | 2 | import 'package:example/src/home.dart'; |
2 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 4 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
@@ -9,9 +10,9 @@ class MyApp extends StatelessWidget { | @@ -9,9 +10,9 @@ class MyApp extends StatelessWidget { | ||
9 | Widget build(BuildContext context) { | 10 | Widget build(BuildContext context) { |
10 | // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it | 11 | // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it |
11 | return ScreenUtilInit( | 12 | return ScreenUtilInit( |
12 | - useInheritedMediaQuery: false, | ||
13 | - builder: (_, child) { | ||
14 | - return MaterialApp( | 13 | + responsiveWidgets: responsiveWidgets, |
14 | + ensureScreenSize: true, | ||
15 | + child: MaterialApp( | ||
15 | debugShowCheckedModeBanner: false, | 16 | debugShowCheckedModeBanner: false, |
16 | title: 'First Method', | 17 | title: 'First Method', |
17 | // You can use the library anywhere in the app even in theme | 18 | // You can use the library anywhere in the app even in theme |
@@ -21,10 +22,8 @@ class MyApp extends StatelessWidget { | @@ -21,10 +22,8 @@ class MyApp extends StatelessWidget { | ||
21 | .black | 22 | .black |
22 | .apply(fontSizeFactor: 1), | 23 | .apply(fontSizeFactor: 1), |
23 | ), | 24 | ), |
24 | - home: child, | ||
25 | - ); | ||
26 | - }, | ||
27 | - child: const HomePage(title: 'First Method'), | 25 | + home: const HomePage(title: 'First Method'), |
26 | + ), | ||
28 | ); | 27 | ); |
29 | } | 28 | } |
30 | } | 29 | } |
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; | @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; | ||
2 | import 'package:flutter/services.dart'; | 2 | import 'package:flutter/services.dart'; |
3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
4 | 4 | ||
5 | -class HomePageScaffold extends StatelessWidget { | 5 | +class HomePageScaffold extends StatelessWidget with SU { |
6 | const HomePageScaffold({Key? key, this.title = ''}) : super(key: key); | 6 | const HomePageScaffold({Key? key, this.title = ''}) : super(key: key); |
7 | 7 | ||
8 | void printScreenInformation(BuildContext context) { | 8 | void printScreenInformation(BuildContext context) { |
@@ -43,7 +43,7 @@ void main() { | @@ -43,7 +43,7 @@ void main() { | ||
43 | data: currentData, | 43 | data: currentData, |
44 | child: ScreenUtilInit( | 44 | child: ScreenUtilInit( |
45 | designSize: designSize, | 45 | designSize: designSize, |
46 | - builder: (context, child) => MaterialApp( | 46 | + child: MaterialApp( |
47 | home: Material( | 47 | home: Material( |
48 | child: TextButton( | 48 | child: TextButton( |
49 | key: _key, | 49 | key: _key, |
@@ -68,6 +68,9 @@ void main() { | @@ -68,6 +68,9 @@ void main() { | ||
68 | // Tests with initial screen size | 68 | // Tests with initial screen size |
69 | testSize(initialSize); | 69 | testSize(initialSize); |
70 | 70 | ||
71 | + // Wait for FutureBuilder to be resolved | ||
72 | + await tester.pumpAndSettle(); | ||
73 | + | ||
71 | // Click On button to simulate changing screen size | 74 | // Click On button to simulate changing screen size |
72 | await tap(); | 75 | await tap(); |
73 | // Tests with bigger screen size | 76 | // Tests with bigger screen size |
@@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" | @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" | ||
60 | // Version | 60 | // Version |
61 | // | 61 | // |
62 | 62 | ||
63 | -#ifdef FLUTTER_BUILD_NUMBER | ||
64 | -#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER | 63 | +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) |
64 | +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD | ||
65 | #else | 65 | #else |
66 | -#define VERSION_AS_NUMBER 1,0,0 | 66 | +#define VERSION_AS_NUMBER 1,0,0,0 |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | -#ifdef FLUTTER_BUILD_NAME | ||
70 | -#define VERSION_AS_STRING #FLUTTER_BUILD_NAME | 69 | +#if defined(FLUTTER_VERSION) |
70 | +#define VERSION_AS_STRING FLUTTER_VERSION | ||
71 | #else | 71 | #else |
72 | #define VERSION_AS_STRING "1.0.0" | 72 | #define VERSION_AS_STRING "1.0.0" |
73 | #endif | 73 | #endif |
@@ -10,3 +10,4 @@ export 'src/r_sizedbox.dart'; | @@ -10,3 +10,4 @@ export 'src/r_sizedbox.dart'; | ||
10 | export 'src/screen_util.dart'; | 10 | export 'src/screen_util.dart'; |
11 | export 'src/screenutil_init.dart'; | 11 | export 'src/screenutil_init.dart'; |
12 | export 'src/size_extension.dart'; | 12 | export 'src/size_extension.dart'; |
13 | +export 'src/screenutil_mixin.dart'; |
lib/src/_flutter_widgets.dart
0 → 100644
1 | +import 'dart:collection'; | ||
2 | + | ||
3 | +final flutterWidgets = HashSet<String>.from({ | ||
4 | + 'AbsorbPointer', | ||
5 | + 'Accumulator', | ||
6 | + 'Action', | ||
7 | + 'ActionDispatcher', | ||
8 | + 'ActionListener', | ||
9 | + 'Actions', | ||
10 | + 'ActivateAction', | ||
11 | + 'ActivateIntent', | ||
12 | + 'Align', | ||
13 | + 'Alignment', | ||
14 | + 'AlignmentDirectional', | ||
15 | + 'AlignmentGeometry', | ||
16 | + 'AlignmentGeometryTween', | ||
17 | + 'AlignmentTween', | ||
18 | + 'AlignTransition', | ||
19 | + 'AlwaysScrollableScrollPhysics', | ||
20 | + 'AlwaysStoppedAnimation', | ||
21 | + 'AndroidView', | ||
22 | + 'AndroidViewSurface', | ||
23 | + 'Animatable', | ||
24 | + 'AnimatedAlign', | ||
25 | + 'AnimatedBuilder', | ||
26 | + 'AnimatedContainer', | ||
27 | + 'AnimatedCrossFade', | ||
28 | + 'AnimatedDefaultTextStyle', | ||
29 | + 'AnimatedFractionallySizedBox', | ||
30 | + 'AnimatedGrid', | ||
31 | + 'AnimatedGridState', | ||
32 | + 'AnimatedList', | ||
33 | + 'AnimatedListState', | ||
34 | + 'AnimatedModalBarrier', | ||
35 | + 'AnimatedOpacity', | ||
36 | + 'AnimatedPadding', | ||
37 | + 'AnimatedPhysicalModel', | ||
38 | + 'AnimatedPositioned', | ||
39 | + 'AnimatedPositionedDirectional', | ||
40 | + 'AnimatedRotation', | ||
41 | + 'AnimatedScale', | ||
42 | + 'AnimatedSize', | ||
43 | + 'AnimatedSlide', | ||
44 | + 'AnimatedSwitcher', | ||
45 | + 'AnimatedWidget', | ||
46 | + 'AnimatedWidgetBaseState', | ||
47 | + 'Animation', | ||
48 | + 'AnimationController', | ||
49 | + 'AnimationMax', | ||
50 | + 'AnimationMean', | ||
51 | + 'AnimationMin', | ||
52 | + 'AnnotatedRegion', | ||
53 | + 'AspectRatio', | ||
54 | + 'AssetBundle', | ||
55 | + 'AssetBundleImageKey', | ||
56 | + 'AssetBundleImageProvider', | ||
57 | + 'AssetImage', | ||
58 | + 'AsyncSnapshot', | ||
59 | + 'AutocompleteHighlightedOption', | ||
60 | + 'AutocompleteNextOptionIntent', | ||
61 | + 'AutocompletePreviousOptionIntent', | ||
62 | + 'AutofillGroup', | ||
63 | + 'AutofillGroupState', | ||
64 | + 'AutofillHints', | ||
65 | + 'AutomaticKeepAlive', | ||
66 | + 'AutomaticNotchedShape', | ||
67 | + 'BackButtonDispatcher', | ||
68 | + 'BackButtonListener', | ||
69 | + 'BackdropFilter', | ||
70 | + 'BallisticScrollActivity', | ||
71 | + 'Banner', | ||
72 | + 'BannerPainter', | ||
73 | + 'Baseline', | ||
74 | + 'BaseTapAndDragGestureRecognizer', | ||
75 | + 'BeveledRectangleBorder', | ||
76 | + 'BlockSemantics', | ||
77 | + 'Border', | ||
78 | + 'BorderDirectional', | ||
79 | + 'BorderRadius', | ||
80 | + 'BorderRadiusDirectional', | ||
81 | + 'BorderRadiusGeometry', | ||
82 | + 'BorderRadiusTween', | ||
83 | + 'BorderSide', | ||
84 | + 'BorderTween', | ||
85 | + 'BottomNavigationBarItem', | ||
86 | + 'BouncingScrollPhysics', | ||
87 | + 'BouncingScrollSimulation', | ||
88 | + 'BoxBorder', | ||
89 | + 'BoxConstraints', | ||
90 | + 'BoxConstraintsTween', | ||
91 | + 'BoxDecoration', | ||
92 | + 'BoxPainter', | ||
93 | + 'BoxScrollView', | ||
94 | + 'BoxShadow', | ||
95 | + 'BuildContext', | ||
96 | + 'Builder', | ||
97 | + 'BuildOwner', | ||
98 | + 'ButtonActivateIntent', | ||
99 | + 'CallbackAction', | ||
100 | + 'CallbackShortcuts', | ||
101 | + 'Canvas', | ||
102 | + 'CapturedThemes', | ||
103 | + 'CatmullRomCurve', | ||
104 | + 'CatmullRomSpline', | ||
105 | + 'Center', | ||
106 | + 'ChangeNotifier', | ||
107 | + 'CharacterActivator', | ||
108 | + 'CharacterRange', | ||
109 | + 'Characters', | ||
110 | + 'CheckedModeBanner', | ||
111 | + 'ChildBackButtonDispatcher', | ||
112 | + 'CircleBorder', | ||
113 | + 'CircularNotchedRectangle', | ||
114 | + 'ClampingScrollPhysics', | ||
115 | + 'ClampingScrollSimulation', | ||
116 | + 'ClipboardStatusNotifier', | ||
117 | + 'ClipContext', | ||
118 | + 'ClipOval', | ||
119 | + 'ClipPath', | ||
120 | + 'ClipRect', | ||
121 | + 'ClipRRect', | ||
122 | + 'Color', | ||
123 | + 'ColoredBox', | ||
124 | + 'ColorFilter', | ||
125 | + 'ColorFiltered', | ||
126 | + 'ColorProperty', | ||
127 | + 'ColorSwatch', | ||
128 | + 'ColorTween', | ||
129 | + 'Column', | ||
130 | + 'ComponentElement', | ||
131 | + 'CompositedTransformFollower', | ||
132 | + 'CompositedTransformTarget', | ||
133 | + 'CompoundAnimation', | ||
134 | + 'ConstantTween', | ||
135 | + 'ConstrainedBox', | ||
136 | + 'ConstrainedLayoutBuilder', | ||
137 | + 'ConstraintsTransformBox', | ||
138 | + 'Container', | ||
139 | + 'ContentInsertionConfiguration', | ||
140 | + 'ContextAction', | ||
141 | + 'ContextMenuButtonItem', | ||
142 | + 'ContextMenuController', | ||
143 | + 'ContinuousRectangleBorder', | ||
144 | + 'CopySelectionTextIntent', | ||
145 | + 'Cubic', | ||
146 | + 'Curve', | ||
147 | + 'Curve2D', | ||
148 | + 'Curve2DSample', | ||
149 | + 'CurvedAnimation', | ||
150 | + 'Curves', | ||
151 | + 'CurveTween', | ||
152 | + 'CustomClipper', | ||
153 | + 'CustomMultiChildLayout', | ||
154 | + 'CustomPaint', | ||
155 | + 'CustomPainter', | ||
156 | + 'CustomPainterSemantics', | ||
157 | + 'CustomScrollView', | ||
158 | + 'CustomSingleChildLayout', | ||
159 | + 'DebugCreator', | ||
160 | + 'DecoratedBox', | ||
161 | + 'DecoratedBoxTransition', | ||
162 | + 'Decoration', | ||
163 | + 'DecorationImage', | ||
164 | + 'DecorationImagePainter', | ||
165 | + 'DecorationTween', | ||
166 | + 'DefaultAssetBundle', | ||
167 | + 'DefaultPlatformMenuDelegate', | ||
168 | + 'DefaultSelectionStyle', | ||
169 | + 'DefaultTextEditingShortcuts', | ||
170 | + 'DefaultTextHeightBehavior', | ||
171 | + 'DefaultTextStyle', | ||
172 | + 'DefaultTextStyleTransition', | ||
173 | + 'DefaultTransitionDelegate', | ||
174 | + 'DefaultWidgetsLocalizations', | ||
175 | + 'DeleteCharacterIntent', | ||
176 | + 'DeleteToLineBreakIntent', | ||
177 | + 'DeleteToNextWordBoundaryIntent', | ||
178 | + 'DesktopTextSelectionToolbarLayoutDelegate', | ||
179 | + 'DevToolsDeepLinkProperty', | ||
180 | + 'DiagnosticsNode', | ||
181 | + 'DirectionalCaretMovementIntent', | ||
182 | + 'DirectionalFocusAction', | ||
183 | + 'DirectionalFocusIntent', | ||
184 | + 'Directionality', | ||
185 | + 'DirectionalTextEditingIntent', | ||
186 | + 'DismissAction', | ||
187 | + 'Dismissible', | ||
188 | + 'DismissIntent', | ||
189 | + 'DismissUpdateDetails', | ||
190 | + 'DisplayFeatureSubScreen', | ||
191 | + 'DisposableBuildContext', | ||
192 | + 'DoNothingAction', | ||
193 | + 'DoNothingAndStopPropagationIntent', | ||
194 | + 'DoNothingAndStopPropagationTextIntent', | ||
195 | + 'DoNothingIntent', | ||
196 | + 'DragDownDetails', | ||
197 | + 'DragEndDetails', | ||
198 | + 'Draggable', | ||
199 | + 'DraggableDetails', | ||
200 | + 'DraggableScrollableActuator', | ||
201 | + 'DraggableScrollableController', | ||
202 | + 'DraggableScrollableNotification', | ||
203 | + 'DraggableScrollableSheet', | ||
204 | + 'DragScrollActivity', | ||
205 | + 'DragStartDetails', | ||
206 | + 'DragTarget', | ||
207 | + 'DragTargetDetails', | ||
208 | + 'DragUpdateDetails', | ||
209 | + 'DrivenScrollActivity', | ||
210 | + 'DualTransitionBuilder', | ||
211 | + 'EdgeDraggingAutoScroller', | ||
212 | + 'EdgeInsets', | ||
213 | + 'EdgeInsetsDirectional', | ||
214 | + 'EdgeInsetsGeometry', | ||
215 | + 'EdgeInsetsGeometryTween', | ||
216 | + 'EdgeInsetsTween', | ||
217 | + 'EditableText', | ||
218 | + 'EditableTextState', | ||
219 | + 'ElasticInCurve', | ||
220 | + 'ElasticInOutCurve', | ||
221 | + 'ElasticOutCurve', | ||
222 | + 'Element', | ||
223 | + 'EmptyTextSelectionControls', | ||
224 | + 'ErrorDescription', | ||
225 | + 'ErrorHint', | ||
226 | + 'ErrorSummary', | ||
227 | + 'ErrorWidget', | ||
228 | + 'ExactAssetImage', | ||
229 | + 'ExcludeFocus', | ||
230 | + 'ExcludeFocusTraversal', | ||
231 | + 'ExcludeSemantics', | ||
232 | + 'Expanded', | ||
233 | + 'ExpandSelectionToDocumentBoundaryIntent', | ||
234 | + 'ExpandSelectionToLineBreakIntent', | ||
235 | + 'ExtendSelectionByCharacterIntent', | ||
236 | + 'ExtendSelectionByPageIntent', | ||
237 | + 'ExtendSelectionToDocumentBoundaryIntent', | ||
238 | + 'ExtendSelectionToLineBreakIntent', | ||
239 | + 'ExtendSelectionToNextParagraphBoundaryIntent', | ||
240 | + 'ExtendSelectionToNextParagraphBoundaryOrCaretLocationIntent', | ||
241 | + 'ExtendSelectionToNextWordBoundaryIntent', | ||
242 | + 'ExtendSelectionToNextWordBoundaryOrCaretLocationIntent', | ||
243 | + 'ExtendSelectionVerticallyToAdjacentLineIntent', | ||
244 | + 'ExtendSelectionVerticallyToAdjacentPageIntent', | ||
245 | + 'FadeInImage', | ||
246 | + 'FadeTransition', | ||
247 | + 'FileImage', | ||
248 | + 'FittedBox', | ||
249 | + 'FittedSizes', | ||
250 | + 'FixedColumnWidth', | ||
251 | + 'FixedExtentMetrics', | ||
252 | + 'FixedExtentScrollController', | ||
253 | + 'FixedExtentScrollPhysics', | ||
254 | + 'FixedScrollMetrics', | ||
255 | + 'Flex', | ||
256 | + 'FlexColumnWidth', | ||
257 | + 'Flexible', | ||
258 | + 'FlippedCurve', | ||
259 | + 'FlippedTweenSequence', | ||
260 | + 'Flow', | ||
261 | + 'FlowDelegate', | ||
262 | + 'FlowPaintingContext', | ||
263 | + 'FlutterErrorDetails', | ||
264 | + 'FlutterLogoDecoration', | ||
265 | + 'Focus', | ||
266 | + 'FocusableActionDetector', | ||
267 | + 'FocusAttachment', | ||
268 | + 'FocusManager', | ||
269 | + 'FocusNode', | ||
270 | + 'FocusOrder', | ||
271 | + 'FocusScope', | ||
272 | + 'FocusScopeNode', | ||
273 | + 'FocusTraversalGroup', | ||
274 | + 'FocusTraversalOrder', | ||
275 | + 'FocusTraversalPolicy', | ||
276 | + 'FontWeight', | ||
277 | + 'ForcePressDetails', | ||
278 | + 'Form', | ||
279 | + 'FormField', | ||
280 | + 'FormFieldState', | ||
281 | + 'FormState', | ||
282 | + 'FractionallySizedBox', | ||
283 | + 'FractionalOffset', | ||
284 | + 'FractionalOffsetTween', | ||
285 | + 'FractionalTranslation', | ||
286 | + 'FractionColumnWidth', | ||
287 | + 'FutureBuilder', | ||
288 | + 'GestureDetector', | ||
289 | + 'GestureRecognizerFactory', | ||
290 | + 'GestureRecognizerFactoryWithHandlers', | ||
291 | + 'GlobalKey', | ||
292 | + 'GlobalObjectKey', | ||
293 | + 'GlowingOverscrollIndicator', | ||
294 | + 'Gradient', | ||
295 | + 'GradientRotation', | ||
296 | + 'GradientTransform', | ||
297 | + 'GridPaper', | ||
298 | + 'GridView', | ||
299 | + 'Hero', | ||
300 | + 'HeroController', | ||
301 | + 'HeroControllerScope', | ||
302 | + 'HeroMode', | ||
303 | + 'HoldScrollActivity', | ||
304 | + 'HSLColor', | ||
305 | + 'HSVColor', | ||
306 | + 'HtmlElementView', | ||
307 | + 'Icon', | ||
308 | + 'IconData', | ||
309 | + 'IconDataProperty', | ||
310 | + 'IconTheme', | ||
311 | + 'IconThemeData', | ||
312 | + 'IdleScrollActivity', | ||
313 | + 'IgnorePointer', | ||
314 | + 'Image', | ||
315 | + 'ImageCache', | ||
316 | + 'ImageCacheStatus', | ||
317 | + 'ImageChunkEvent', | ||
318 | + 'ImageConfiguration', | ||
319 | + 'ImageFiltered', | ||
320 | + 'ImageIcon', | ||
321 | + 'ImageInfo', | ||
322 | + 'ImageProvider', | ||
323 | + 'ImageShader', | ||
324 | + 'ImageSizeInfo', | ||
325 | + 'ImageStream', | ||
326 | + 'ImageStreamCompleter', | ||
327 | + 'ImageStreamCompleterHandle', | ||
328 | + 'ImageStreamListener', | ||
329 | + 'ImageTilingInfo', | ||
330 | + 'ImplicitlyAnimatedWidget', | ||
331 | + 'ImplicitlyAnimatedWidgetState', | ||
332 | + 'IndexedSemantics', | ||
333 | + 'IndexedSlot', | ||
334 | + 'IndexedStack', | ||
335 | + 'InheritedElement', | ||
336 | + 'InheritedModel', | ||
337 | + 'InheritedModelElement', | ||
338 | + 'InheritedNotifier', | ||
339 | + 'InheritedTheme', | ||
340 | + 'InheritedWidget', | ||
341 | + 'InlineSpan', | ||
342 | + 'InlineSpanSemanticsInformation', | ||
343 | + 'InspectorSelection', | ||
344 | + 'InspectorSerializationDelegate', | ||
345 | + 'Intent', | ||
346 | + 'InteractiveViewer', | ||
347 | + 'Interval', | ||
348 | + 'IntrinsicColumnWidth', | ||
349 | + 'IntrinsicHeight', | ||
350 | + 'IntrinsicWidth', | ||
351 | + 'IntTween', | ||
352 | + 'KeepAlive', | ||
353 | + 'KeepAliveHandle', | ||
354 | + 'KeepAliveNotification', | ||
355 | + 'Key', | ||
356 | + 'KeyboardInsertedContent', | ||
357 | + 'KeyboardListener', | ||
358 | + 'KeyedSubtree', | ||
359 | + 'KeyEvent', | ||
360 | + 'KeySet', | ||
361 | + 'LabeledGlobalKey', | ||
362 | + 'LayerLink', | ||
363 | + 'LayoutBuilder', | ||
364 | + 'LayoutChangedNotification', | ||
365 | + 'LayoutId', | ||
366 | + 'LeafRenderObjectElement', | ||
367 | + 'LeafRenderObjectWidget', | ||
368 | + 'LexicalFocusOrder', | ||
369 | + 'LimitedBox', | ||
370 | + 'LinearBorder', | ||
371 | + 'LinearBorderEdge', | ||
372 | + 'LinearGradient', | ||
373 | + 'ListBody', | ||
374 | + 'Listenable', | ||
375 | + 'ListenableBuilder', | ||
376 | + 'Listener', | ||
377 | + 'ListView', | ||
378 | + 'ListWheelChildBuilderDelegate', | ||
379 | + 'ListWheelChildDelegate', | ||
380 | + 'ListWheelChildListDelegate', | ||
381 | + 'ListWheelChildLoopingListDelegate', | ||
382 | + 'ListWheelElement', | ||
383 | + 'ListWheelScrollView', | ||
384 | + 'ListWheelViewport', | ||
385 | + 'Locale', | ||
386 | + 'LocalHistoryEntry', | ||
387 | + 'Localizations', | ||
388 | + 'LocalizationsDelegate', | ||
389 | + 'LocalKey', | ||
390 | + 'LogicalKeySet', | ||
391 | + 'LongPressDraggable', | ||
392 | + 'LongPressEndDetails', | ||
393 | + 'LongPressMoveUpdateDetails', | ||
394 | + 'LongPressStartDetails', | ||
395 | + 'LookupBoundary', | ||
396 | + 'MagnifierController', | ||
397 | + 'MagnifierDecoration', | ||
398 | + 'MagnifierInfo', | ||
399 | + 'MaskFilter', | ||
400 | + 'Matrix4', | ||
401 | + 'Matrix4Tween', | ||
402 | + 'MatrixUtils', | ||
403 | + 'MaxColumnWidth', | ||
404 | + 'MediaQuery', | ||
405 | + 'MediaQueryData', | ||
406 | + 'MemoryImage', | ||
407 | + 'MergeSemantics', | ||
408 | + 'MetaData', | ||
409 | + 'MinColumnWidth', | ||
410 | + 'ModalBarrier', | ||
411 | + 'ModalRoute', | ||
412 | + 'MouseCursor', | ||
413 | + 'MouseRegion', | ||
414 | + 'MultiChildLayoutDelegate', | ||
415 | + 'MultiChildRenderObjectElement', | ||
416 | + 'MultiChildRenderObjectWidget', | ||
417 | + 'MultiFrameImageStreamCompleter', | ||
418 | + 'MultiSelectableSelectionContainerDelegate', | ||
419 | + 'NavigationToolbar', | ||
420 | + 'Navigator', | ||
421 | + 'NavigatorObserver', | ||
422 | + 'NavigatorState', | ||
423 | + 'NestedScrollView', | ||
424 | + 'NestedScrollViewState', | ||
425 | + 'NestedScrollViewViewport', | ||
426 | + 'NetworkImage', | ||
427 | + 'NeverScrollableScrollPhysics', | ||
428 | + 'NextFocusAction', | ||
429 | + 'NextFocusIntent', | ||
430 | + 'NotchedShape', | ||
431 | + 'Notification', | ||
432 | + 'NotificationListener', | ||
433 | + 'NumericFocusOrder', | ||
434 | + 'ObjectKey', | ||
435 | + 'Offset', | ||
436 | + 'Offstage', | ||
437 | + 'OneFrameImageStreamCompleter', | ||
438 | + 'Opacity', | ||
439 | + 'OrderedTraversalPolicy', | ||
440 | + 'OrientationBuilder', | ||
441 | + 'OutlinedBorder', | ||
442 | + 'OvalBorder', | ||
443 | + 'OverflowBar', | ||
444 | + 'OverflowBox', | ||
445 | + 'Overlay', | ||
446 | + 'OverlayEntry', | ||
447 | + 'OverlayPortal', | ||
448 | + 'OverlayPortalController', | ||
449 | + 'OverlayRoute', | ||
450 | + 'OverlayState', | ||
451 | + 'OverscrollIndicatorNotification', | ||
452 | + 'OverscrollNotification', | ||
453 | + 'Padding', | ||
454 | + 'Page', | ||
455 | + 'PageController', | ||
456 | + 'PageMetrics', | ||
457 | + 'PageRoute', | ||
458 | + 'PageRouteBuilder', | ||
459 | + 'PageScrollPhysics', | ||
460 | + 'PageStorage', | ||
461 | + 'PageStorageBucket', | ||
462 | + 'PageStorageKey', | ||
463 | + 'PageView', | ||
464 | + 'Paint', | ||
465 | + 'PaintingContext', | ||
466 | + 'ParametricCurve', | ||
467 | + 'ParentDataElement', | ||
468 | + 'ParentDataWidget', | ||
469 | + 'PasteTextIntent', | ||
470 | + 'Path', | ||
471 | + 'PerformanceOverlay', | ||
472 | + 'PhysicalModel', | ||
473 | + 'PhysicalShape', | ||
474 | + 'Placeholder', | ||
475 | + 'PlaceholderDimensions', | ||
476 | + 'PlaceholderSpan', | ||
477 | + 'PlatformMenu', | ||
478 | + 'PlatformMenuBar', | ||
479 | + 'PlatformMenuDelegate', | ||
480 | + 'PlatformMenuItem', | ||
481 | + 'PlatformMenuItemGroup', | ||
482 | + 'PlatformProvidedMenuItem', | ||
483 | + 'PlatformRouteInformationProvider', | ||
484 | + 'PlatformSelectableRegionContextMenu', | ||
485 | + 'PlatformViewCreationParams', | ||
486 | + 'PlatformViewLink', | ||
487 | + 'PlatformViewSurface', | ||
488 | + 'PointerCancelEvent', | ||
489 | + 'PointerDownEvent', | ||
490 | + 'PointerEvent', | ||
491 | + 'PointerMoveEvent', | ||
492 | + 'PointerUpEvent', | ||
493 | + 'PopupRoute', | ||
494 | + 'Positioned', | ||
495 | + 'PositionedDirectional', | ||
496 | + 'PositionedTransition', | ||
497 | + 'PreferredSize', | ||
498 | + 'PreferredSizeWidget', | ||
499 | + 'PreviousFocusAction', | ||
500 | + 'PreviousFocusIntent', | ||
501 | + 'PrimaryScrollController', | ||
502 | + 'PrioritizedAction', | ||
503 | + 'PrioritizedIntents', | ||
504 | + 'ProxyAnimation', | ||
505 | + 'ProxyElement', | ||
506 | + 'ProxyWidget', | ||
507 | + 'RadialGradient', | ||
508 | + 'Radius', | ||
509 | + 'RangeMaintainingScrollPhysics', | ||
510 | + 'RawAutocomplete', | ||
511 | + 'RawDialogRoute', | ||
512 | + 'RawGestureDetector', | ||
513 | + 'RawGestureDetectorState', | ||
514 | + 'RawImage', | ||
515 | + 'RawKeyboardListener', | ||
516 | + 'RawKeyEvent', | ||
517 | + 'RawMagnifier', | ||
518 | + 'RawScrollbar', | ||
519 | + 'RawScrollbarState', | ||
520 | + 'ReadingOrderTraversalPolicy', | ||
521 | + 'Rect', | ||
522 | + 'RectTween', | ||
523 | + 'RedoTextIntent', | ||
524 | + 'RelativePositionedTransition', | ||
525 | + 'RelativeRect', | ||
526 | + 'RelativeRectTween', | ||
527 | + 'RenderBox', | ||
528 | + 'RenderNestedScrollViewViewport', | ||
529 | + 'RenderObject', | ||
530 | + 'RenderObjectElement', | ||
531 | + 'RenderObjectToWidgetAdapter', | ||
532 | + 'RenderObjectToWidgetElement', | ||
533 | + 'RenderObjectWidget', | ||
534 | + 'RenderSemanticsGestureHandler', | ||
535 | + 'RenderSliverOverlapAbsorber', | ||
536 | + 'RenderSliverOverlapInjector', | ||
537 | + 'RenderTapRegion', | ||
538 | + 'RenderTapRegionSurface', | ||
539 | + 'ReorderableDelayedDragStartListener', | ||
540 | + 'ReorderableDragStartListener', | ||
541 | + 'ReorderableList', | ||
542 | + 'ReorderableListState', | ||
543 | + 'RepaintBoundary', | ||
544 | + 'ReplaceTextIntent', | ||
545 | + 'RequestFocusAction', | ||
546 | + 'RequestFocusIntent', | ||
547 | + 'ResizeImage', | ||
548 | + 'ResizeImageKey', | ||
549 | + 'RestorableBool', | ||
550 | + 'RestorableBoolN', | ||
551 | + 'RestorableChangeNotifier', | ||
552 | + 'RestorableDateTime', | ||
553 | + 'RestorableDateTimeN', | ||
554 | + 'RestorableDouble', | ||
555 | + 'RestorableDoubleN', | ||
556 | + 'RestorableEnum', | ||
557 | + 'RestorableEnumN', | ||
558 | + 'RestorableInt', | ||
559 | + 'RestorableIntN', | ||
560 | + 'RestorableListenable', | ||
561 | + 'RestorableNum', | ||
562 | + 'RestorableNumN', | ||
563 | + 'RestorableProperty', | ||
564 | + 'RestorableRouteFuture', | ||
565 | + 'RestorableString', | ||
566 | + 'RestorableStringN', | ||
567 | + 'RestorableTextEditingController', | ||
568 | + 'RestorableValue', | ||
569 | + 'RestorationBucket', | ||
570 | + 'RestorationScope', | ||
571 | + 'ReverseAnimation', | ||
572 | + 'ReverseTween', | ||
573 | + 'RichText', | ||
574 | + 'RootBackButtonDispatcher', | ||
575 | + 'RootRenderObjectElement', | ||
576 | + 'RootRestorationScope', | ||
577 | + 'RotatedBox', | ||
578 | + 'RotationTransition', | ||
579 | + 'RoundedRectangleBorder', | ||
580 | + 'Route', | ||
581 | + 'RouteAware', | ||
582 | + 'RouteInformation', | ||
583 | + 'RouteInformationParser', | ||
584 | + 'RouteInformationProvider', | ||
585 | + 'RouteObserver', | ||
586 | + 'Router', | ||
587 | + 'RouterConfig', | ||
588 | + 'RouterDelegate', | ||
589 | + 'RouteSettings', | ||
590 | + 'RouteTransitionRecord', | ||
591 | + 'Row', | ||
592 | + 'RRect', | ||
593 | + 'RSTransform', | ||
594 | + 'SafeArea', | ||
595 | + 'SawTooth', | ||
596 | + 'ScaleEndDetails', | ||
597 | + 'ScaleStartDetails', | ||
598 | + 'ScaleTransition', | ||
599 | + 'ScaleUpdateDetails', | ||
600 | + 'Scrollable', | ||
601 | + 'ScrollableDetails', | ||
602 | + 'ScrollableState', | ||
603 | + 'ScrollAction', | ||
604 | + 'ScrollActivity', | ||
605 | + 'ScrollActivityDelegate', | ||
606 | + 'ScrollAwareImageProvider', | ||
607 | + 'ScrollbarPainter', | ||
608 | + 'ScrollBehavior', | ||
609 | + 'ScrollConfiguration', | ||
610 | + 'ScrollContext', | ||
611 | + 'ScrollController', | ||
612 | + 'ScrollDragController', | ||
613 | + 'ScrollEndNotification', | ||
614 | + 'ScrollHoldController', | ||
615 | + 'ScrollIncrementDetails', | ||
616 | + 'ScrollIntent', | ||
617 | + 'ScrollMetricsNotification', | ||
618 | + 'ScrollNotification', | ||
619 | + 'ScrollNotificationObserver', | ||
620 | + 'ScrollNotificationObserverState', | ||
621 | + 'ScrollPhysics', | ||
622 | + 'ScrollPosition', | ||
623 | + 'ScrollPositionWithSingleContext', | ||
624 | + 'ScrollSpringSimulation', | ||
625 | + 'ScrollStartNotification', | ||
626 | + 'ScrollToDocumentBoundaryIntent', | ||
627 | + 'ScrollUpdateNotification', | ||
628 | + 'ScrollView', | ||
629 | + 'SelectableRegion', | ||
630 | + 'SelectableRegionState', | ||
631 | + 'SelectAction', | ||
632 | + 'SelectAllTextIntent', | ||
633 | + 'SelectIntent', | ||
634 | + 'SelectionContainer', | ||
635 | + 'SelectionContainerDelegate', | ||
636 | + 'SelectionOverlay', | ||
637 | + 'SelectionRegistrarScope', | ||
638 | + 'Semantics', | ||
639 | + 'SemanticsDebugger', | ||
640 | + 'SemanticsGestureDelegate', | ||
641 | + 'Shader', | ||
642 | + 'ShaderMask', | ||
643 | + 'ShaderWarmUp', | ||
644 | + 'Shadow', | ||
645 | + 'ShapeBorder', | ||
646 | + 'ShapeBorderClipper', | ||
647 | + 'ShapeDecoration', | ||
648 | + 'SharedAppData', | ||
649 | + 'ShortcutActivator', | ||
650 | + 'ShortcutManager', | ||
651 | + 'ShortcutMapProperty', | ||
652 | + 'ShortcutRegistrar', | ||
653 | + 'ShortcutRegistry', | ||
654 | + 'ShortcutRegistryEntry', | ||
655 | + 'Shortcuts', | ||
656 | + 'ShortcutSerialization', | ||
657 | + 'ShrinkWrappingViewport', | ||
658 | + 'Simulation', | ||
659 | + 'SingleActivator', | ||
660 | + 'SingleChildLayoutDelegate', | ||
661 | + 'SingleChildRenderObjectElement', | ||
662 | + 'SingleChildRenderObjectWidget', | ||
663 | + 'SingleChildScrollView', | ||
664 | + 'Size', | ||
665 | + 'SizeChangedLayoutNotification', | ||
666 | + 'SizeChangedLayoutNotifier', | ||
667 | + 'SizedBox', | ||
668 | + 'SizedOverflowBox', | ||
669 | + 'SizeTransition', | ||
670 | + 'SizeTween', | ||
671 | + 'SlideTransition', | ||
672 | + 'SliverAnimatedGrid', | ||
673 | + 'SliverAnimatedGridState', | ||
674 | + 'SliverAnimatedList', | ||
675 | + 'SliverAnimatedListState', | ||
676 | + 'SliverAnimatedOpacity', | ||
677 | + 'SliverChildBuilderDelegate', | ||
678 | + 'SliverChildDelegate', | ||
679 | + 'SliverChildListDelegate', | ||
680 | + 'SliverFadeTransition', | ||
681 | + 'SliverFillRemaining', | ||
682 | + 'SliverFillViewport', | ||
683 | + 'SliverFixedExtentList', | ||
684 | + 'SliverGrid', | ||
685 | + 'SliverGridDelegate', | ||
686 | + 'SliverGridDelegateWithFixedCrossAxisCount', | ||
687 | + 'SliverGridDelegateWithMaxCrossAxisExtent', | ||
688 | + 'SliverIgnorePointer', | ||
689 | + 'SliverLayoutBuilder', | ||
690 | + 'SliverList', | ||
691 | + 'SliverMultiBoxAdaptorElement', | ||
692 | + 'SliverMultiBoxAdaptorWidget', | ||
693 | + 'SliverOffstage', | ||
694 | + 'SliverOpacity', | ||
695 | + 'SliverOverlapAbsorber', | ||
696 | + 'SliverOverlapAbsorberHandle', | ||
697 | + 'SliverOverlapInjector', | ||
698 | + 'SliverPadding', | ||
699 | + 'SliverPersistentHeader', | ||
700 | + 'SliverPersistentHeaderDelegate', | ||
701 | + 'SliverPrototypeExtentList', | ||
702 | + 'SliverReorderableList', | ||
703 | + 'SliverReorderableListState', | ||
704 | + 'SliverSafeArea', | ||
705 | + 'SliverToBoxAdapter', | ||
706 | + 'SliverVisibility', | ||
707 | + 'SliverWithKeepAliveWidget', | ||
708 | + 'SlottedRenderObjectElement', | ||
709 | + 'SnapshotController', | ||
710 | + 'SnapshotPainter', | ||
711 | + 'SnapshotWidget', | ||
712 | + 'Spacer', | ||
713 | + 'SpellCheckConfiguration', | ||
714 | + 'SpringDescription', | ||
715 | + 'Stack', | ||
716 | + 'StadiumBorder', | ||
717 | + 'StarBorder', | ||
718 | + 'State', | ||
719 | + 'StatefulBuilder', | ||
720 | + 'StatefulElement', | ||
721 | + 'StatefulWidget', | ||
722 | + 'StatelessElement', | ||
723 | + 'StatelessWidget', | ||
724 | + 'StatusTransitionWidget', | ||
725 | + 'StepTween', | ||
726 | + 'StreamBuilder', | ||
727 | + 'StreamBuilderBase', | ||
728 | + 'StretchingOverscrollIndicator', | ||
729 | + 'StrutStyle', | ||
730 | + 'SweepGradient', | ||
731 | + 'SystemMouseCursors', | ||
732 | + 'Table', | ||
733 | + 'TableBorder', | ||
734 | + 'TableCell', | ||
735 | + 'TableColumnWidth', | ||
736 | + 'TableRow', | ||
737 | + 'TapAndDragGestureRecognizer', | ||
738 | + 'TapAndHorizontalDragGestureRecognizer', | ||
739 | + 'TapAndPanGestureRecognizer', | ||
740 | + 'TapDownDetails', | ||
741 | + 'TapDragDownDetails', | ||
742 | + 'TapDragEndDetails', | ||
743 | + 'TapDragStartDetails', | ||
744 | + 'TapDragUpdateDetails', | ||
745 | + 'TapDragUpDetails', | ||
746 | + 'TapRegion', | ||
747 | + 'TapRegionRegistry', | ||
748 | + 'TapRegionSurface', | ||
749 | + 'TapUpDetails', | ||
750 | + 'Text', | ||
751 | + 'TextAlignVertical', | ||
752 | + 'TextBox', | ||
753 | + 'TextDecoration', | ||
754 | + 'TextEditingController', | ||
755 | + 'TextEditingValue', | ||
756 | + 'TextFieldTapRegion', | ||
757 | + 'TextHeightBehavior', | ||
758 | + 'TextInputType', | ||
759 | + 'TextMagnifierConfiguration', | ||
760 | + 'TextPainter', | ||
761 | + 'TextPosition', | ||
762 | + 'TextRange', | ||
763 | + 'TextSelection', | ||
764 | + 'TextSelectionControls', | ||
765 | + 'TextSelectionGestureDetector', | ||
766 | + 'TextSelectionGestureDetectorBuilder', | ||
767 | + 'TextSelectionGestureDetectorBuilderDelegate', | ||
768 | + 'TextSelectionOverlay', | ||
769 | + 'TextSelectionPoint', | ||
770 | + 'TextSelectionToolbarAnchors', | ||
771 | + 'TextSelectionToolbarLayoutDelegate', | ||
772 | + 'TextSpan', | ||
773 | + 'TextStyle', | ||
774 | + 'TextStyleTween', | ||
775 | + 'Texture', | ||
776 | + 'ThreePointCubic', | ||
777 | + 'Threshold', | ||
778 | + 'TickerFuture', | ||
779 | + 'TickerMode', | ||
780 | + 'TickerProvider', | ||
781 | + 'Title', | ||
782 | + 'Tolerance', | ||
783 | + 'ToolbarItemsParentData', | ||
784 | + 'ToolbarOptions', | ||
785 | + 'TrackingScrollController', | ||
786 | + 'TrainHoppingAnimation', | ||
787 | + 'Transform', | ||
788 | + 'TransformationController', | ||
789 | + 'TransformProperty', | ||
790 | + 'TransitionDelegate', | ||
791 | + 'TransitionRoute', | ||
792 | + 'TransposeCharactersIntent', | ||
793 | + 'Tween', | ||
794 | + 'TweenAnimationBuilder', | ||
795 | + 'TweenSequence', | ||
796 | + 'TweenSequenceItem', | ||
797 | + 'UiKitView', | ||
798 | + 'UnconstrainedBox', | ||
799 | + 'UndoHistory', | ||
800 | + 'UndoHistoryController', | ||
801 | + 'UndoHistoryState', | ||
802 | + 'UndoHistoryValue', | ||
803 | + 'UndoTextIntent', | ||
804 | + 'UniqueKey', | ||
805 | + 'UniqueWidget', | ||
806 | + 'UnmanagedRestorationScope', | ||
807 | + 'UpdateSelectionIntent', | ||
808 | + 'UserScrollNotification', | ||
809 | + 'ValueKey', | ||
810 | + 'ValueListenableBuilder', | ||
811 | + 'ValueNotifier', | ||
812 | + 'Velocity', | ||
813 | + 'View', | ||
814 | + 'Viewport', | ||
815 | + 'Visibility', | ||
816 | + 'VoidCallbackAction', | ||
817 | + 'VoidCallbackIntent', | ||
818 | + 'Widget', | ||
819 | + 'WidgetInspector', | ||
820 | + 'WidgetOrderTraversalPolicy', | ||
821 | + 'WidgetsApp', | ||
822 | + 'WidgetsBindingObserver', | ||
823 | + 'WidgetsFlutterBinding', | ||
824 | + 'WidgetsLocalizations', | ||
825 | + 'WidgetSpan', | ||
826 | + 'WidgetToRenderBoxAdapter', | ||
827 | + 'WillPopScope', | ||
828 | + 'WordBoundary', | ||
829 | + 'Wrap' | ||
830 | +}); |
@@ -4,11 +4,12 @@ | @@ -4,11 +4,12 @@ | ||
4 | */ | 4 | */ |
5 | 5 | ||
6 | import 'dart:math' show min, max; | 6 | import 'dart:math' show min, max; |
7 | -import 'dart:ui' show FlutterView; | ||
8 | -import 'dart:async' show Completer; | 7 | +import 'dart:ui' as ui show FlutterView; |
9 | 8 | ||
10 | import 'package:flutter/widgets.dart'; | 9 | import 'package:flutter/widgets.dart'; |
11 | 10 | ||
11 | +typedef FontSizeResolver = double Function(num fontSize, ScreenUtil instance); | ||
12 | + | ||
12 | class ScreenUtil { | 13 | class ScreenUtil { |
13 | static const Size defaultSize = Size(360, 690); | 14 | static const Size defaultSize = Size(360, 690); |
14 | static ScreenUtil _instance = ScreenUtil._(); | 15 | static ScreenUtil _instance = ScreenUtil._(); |
@@ -20,17 +21,14 @@ class ScreenUtil { | @@ -20,17 +21,14 @@ class ScreenUtil { | ||
20 | ///屏幕方向 | 21 | ///屏幕方向 |
21 | late Orientation _orientation; | 22 | late Orientation _orientation; |
22 | 23 | ||
23 | - late double _screenWidth; | ||
24 | - late double _screenHeight; | ||
25 | late bool _minTextAdapt; | 24 | late bool _minTextAdapt; |
26 | - BuildContext? _context; | 25 | + late MediaQueryData _data; |
27 | late bool _splitScreenMode; | 26 | late bool _splitScreenMode; |
27 | + FontSizeResolver? fontSizeResolver; | ||
28 | 28 | ||
29 | ScreenUtil._(); | 29 | ScreenUtil._(); |
30 | 30 | ||
31 | - factory ScreenUtil() { | ||
32 | - return _instance; | ||
33 | - } | 31 | + factory ScreenUtil() => _instance; |
34 | 32 | ||
35 | /// Manually wait for window size to be initialized | 33 | /// Manually wait for window size to be initialized |
36 | /// | 34 | /// |
@@ -55,19 +53,25 @@ class ScreenUtil { | @@ -55,19 +53,25 @@ class ScreenUtil { | ||
55 | /// ) | 53 | /// ) |
56 | /// ``` | 54 | /// ``` |
57 | static Future<void> ensureScreenSize([ | 55 | static Future<void> ensureScreenSize([ |
58 | - FlutterView? window, | 56 | + ui.FlutterView? window, |
59 | Duration duration = const Duration(milliseconds: 10), | 57 | Duration duration = const Duration(milliseconds: 10), |
60 | ]) async { | 58 | ]) async { |
61 | final binding = WidgetsFlutterBinding.ensureInitialized(); | 59 | final binding = WidgetsFlutterBinding.ensureInitialized(); |
62 | - window ??= WidgetsBinding.instance.platformDispatcher.implicitView; | ||
63 | - | ||
64 | - if (window?.physicalGeometry.isEmpty == true) { | ||
65 | - return Future.delayed(duration, () async { | ||
66 | binding.deferFirstFrame(); | 60 | binding.deferFirstFrame(); |
67 | - await ensureScreenSize(window, duration); | ||
68 | - return binding.allowFirstFrame(); | ||
69 | - }); | 61 | + |
62 | + await Future.doWhile(() { | ||
63 | + if (window == null) { | ||
64 | + window = binding.platformDispatcher.implicitView; | ||
70 | } | 65 | } |
66 | + | ||
67 | + if (window == null || window!.physicalSize.isEmpty) { | ||
68 | + return Future.delayed(duration, () => true); | ||
69 | + } | ||
70 | + | ||
71 | + return false; | ||
72 | + }); | ||
73 | + | ||
74 | + binding.allowFirstFrame(); | ||
71 | } | 75 | } |
72 | 76 | ||
73 | Set<Element>? _elementsToRebuild; | 77 | Set<Element>? _elementsToRebuild; |
@@ -88,44 +92,78 @@ class ScreenUtil { | @@ -88,44 +92,78 @@ class ScreenUtil { | ||
88 | } | 92 | } |
89 | } | 93 | } |
90 | 94 | ||
91 | - /// Initializing the library. | ||
92 | - static Future<void> init(BuildContext context, | ||
93 | - {Size designSize = defaultSize, | ||
94 | - bool splitScreenMode = false, | ||
95 | - bool minTextAdapt = false, | ||
96 | - bool scaleByHeight = false}) async { | ||
97 | - final mediaQueryContext = | ||
98 | - context.getElementForInheritedWidgetOfExactType<MediaQuery>(); | ||
99 | - | ||
100 | - final initCompleter = Completer<void>(); | 95 | + static void configure({ |
96 | + MediaQueryData? data, | ||
97 | + Size? designSize, | ||
98 | + bool? splitScreenMode, | ||
99 | + bool? minTextAdapt, | ||
100 | + FontSizeResolver? fontSizeResolver, | ||
101 | + }) { | ||
102 | + try { | ||
103 | + if (data != null) | ||
104 | + _instance._data = data; | ||
105 | + else | ||
106 | + data = _instance._data; | ||
101 | 107 | ||
102 | - WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((_) { | ||
103 | - mediaQueryContext?.visitChildElements((el) => _instance._context = el); | ||
104 | - if (_instance._context != null) initCompleter.complete(); | ||
105 | - }); | 108 | + if (designSize != null) |
109 | + _instance._uiSize = designSize; | ||
110 | + else | ||
111 | + designSize = _instance._uiSize; | ||
112 | + } catch (_) { | ||
113 | + throw Exception( | ||
114 | + 'You must either use ScreenUtil.init or ScreenUtilInit first'); | ||
115 | + } | ||
106 | 116 | ||
107 | - final deviceData = MediaQuery.maybeOf(context).nonEmptySizeOrNull(); | 117 | + final MediaQueryData? deviceData = data.nonEmptySizeOrNull(); |
118 | + final Size deviceSize = deviceData?.size ?? designSize; | ||
108 | 119 | ||
109 | - final deviceSize = deviceData?.size ?? designSize; | ||
110 | final orientation = deviceData?.orientation ?? | 120 | final orientation = deviceData?.orientation ?? |
111 | (deviceSize.width > deviceSize.height | 121 | (deviceSize.width > deviceSize.height |
112 | ? Orientation.landscape | 122 | ? Orientation.landscape |
113 | : Orientation.portrait); | 123 | : Orientation.portrait); |
114 | 124 | ||
115 | _instance | 125 | _instance |
116 | - .._context = scaleByHeight ? null : context | ||
117 | - .._uiSize = designSize | ||
118 | - .._splitScreenMode = splitScreenMode | ||
119 | - .._minTextAdapt = minTextAdapt | ||
120 | - .._orientation = orientation | ||
121 | - .._screenWidth = scaleByHeight | ||
122 | - ? (deviceSize.height * designSize.width) / designSize.height | ||
123 | - : deviceSize.width | ||
124 | - .._screenHeight = deviceSize.height; | 126 | + ..fontSizeResolver = fontSizeResolver ?? _instance.fontSizeResolver |
127 | + .._minTextAdapt = minTextAdapt ?? _instance._minTextAdapt | ||
128 | + .._splitScreenMode = splitScreenMode ?? _instance._splitScreenMode | ||
129 | + .._orientation = orientation; | ||
125 | 130 | ||
126 | _instance._elementsToRebuild?.forEach((el) => el.markNeedsBuild()); | 131 | _instance._elementsToRebuild?.forEach((el) => el.markNeedsBuild()); |
132 | + } | ||
133 | + | ||
134 | + /// Initializing the library. | ||
135 | + static void init( | ||
136 | + BuildContext context, { | ||
137 | + Size designSize = defaultSize, | ||
138 | + bool splitScreenMode = false, | ||
139 | + bool minTextAdapt = false, | ||
140 | + FontSizeResolver? fontSizeResolver, | ||
141 | + }) { | ||
142 | + return configure( | ||
143 | + data: MediaQuery.maybeOf(context), | ||
144 | + designSize: designSize, | ||
145 | + splitScreenMode: splitScreenMode, | ||
146 | + minTextAdapt: minTextAdapt, | ||
147 | + fontSizeResolver: fontSizeResolver, | ||
148 | + ); | ||
149 | + } | ||
127 | 150 | ||
128 | - return initCompleter.future; | 151 | + static Future<void> ensureScreenSizeAndInit( |
152 | + BuildContext context, { | ||
153 | + Size designSize = defaultSize, | ||
154 | + bool splitScreenMode = false, | ||
155 | + bool minTextAdapt = false, | ||
156 | + FontSizeResolver? fontSizeResolver, | ||
157 | + }) { | ||
158 | + return ScreenUtil.ensureScreenSize().then((_) { | ||
159 | + return configure( | ||
160 | + data: MediaQuery.maybeOf(context), | ||
161 | + designSize: designSize, | ||
162 | + minTextAdapt: minTextAdapt, | ||
163 | + splitScreenMode: splitScreenMode, | ||
164 | + fontSizeResolver: fontSizeResolver, | ||
165 | + ); | ||
166 | + }); | ||
129 | } | 167 | } |
130 | 168 | ||
131 | ///获取屏幕方向 | 169 | ///获取屏幕方向 |
@@ -134,39 +172,33 @@ class ScreenUtil { | @@ -134,39 +172,33 @@ class ScreenUtil { | ||
134 | 172 | ||
135 | /// 每个逻辑像素的字体像素数,字体的缩放比例 | 173 | /// 每个逻辑像素的字体像素数,字体的缩放比例 |
136 | /// The number of font pixels for each logical pixel. | 174 | /// The number of font pixels for each logical pixel. |
137 | - double get textScaleFactor => | ||
138 | - _context != null ? MediaQuery.of(_context!).textScaleFactor : 1; | 175 | + double get textScaleFactor => _data.textScaleFactor; |
139 | 176 | ||
140 | /// 设备的像素密度 | 177 | /// 设备的像素密度 |
141 | /// The size of the media in logical pixels (e.g, the size of the screen). | 178 | /// The size of the media in logical pixels (e.g, the size of the screen). |
142 | - double? get pixelRatio => | ||
143 | - _context != null ? MediaQuery.of(_context!).devicePixelRatio : 1; | 179 | + double? get pixelRatio => _data.devicePixelRatio; |
144 | 180 | ||
145 | /// 当前设备宽度 dp | 181 | /// 当前设备宽度 dp |
146 | /// The horizontal extent of this size. | 182 | /// The horizontal extent of this size. |
147 | - double get screenWidth => | ||
148 | - _context != null ? MediaQuery.of(_context!).size.width : _screenWidth; | 183 | + double get screenWidth => _data.size.width; |
149 | 184 | ||
150 | ///当前设备高度 dp | 185 | ///当前设备高度 dp |
151 | ///The vertical extent of this size. dp | 186 | ///The vertical extent of this size. dp |
152 | - double get screenHeight => | ||
153 | - _context != null ? MediaQuery.of(_context!).size.height : _screenHeight; | 187 | + double get screenHeight => _data.size.height; |
154 | 188 | ||
155 | /// 状态栏高度 dp 刘海屏会更高 | 189 | /// 状态栏高度 dp 刘海屏会更高 |
156 | /// The offset from the top, in dp | 190 | /// The offset from the top, in dp |
157 | - double get statusBarHeight => | ||
158 | - _context == null ? 0 : MediaQuery.of(_context!).padding.top; | 191 | + double get statusBarHeight => _data.padding.top; |
159 | 192 | ||
160 | /// 底部安全区距离 dp | 193 | /// 底部安全区距离 dp |
161 | /// The offset from the bottom, in dp | 194 | /// The offset from the bottom, in dp |
162 | - double get bottomBarHeight => | ||
163 | - _context == null ? 0 : MediaQuery.of(_context!).padding.bottom; | 195 | + double get bottomBarHeight => _data.padding.bottom; |
164 | 196 | ||
165 | /// 实际尺寸与UI设计的比例 | 197 | /// 实际尺寸与UI设计的比例 |
166 | /// The ratio of actual width to UI design | 198 | /// The ratio of actual width to UI design |
167 | double get scaleWidth => screenWidth / _uiSize.width; | 199 | double get scaleWidth => screenWidth / _uiSize.width; |
168 | 200 | ||
169 | - /// /// The ratio of actual height to UI design | 201 | + /// The ratio of actual height to UI design |
170 | double get scaleHeight => | 202 | double get scaleHeight => |
171 | (_splitScreenMode ? max(screenHeight, 700) : screenHeight) / | 203 | (_splitScreenMode ? max(screenHeight, 700) : screenHeight) / |
172 | _uiSize.height; | 204 | _uiSize.height; |
@@ -195,24 +227,44 @@ class ScreenUtil { | @@ -195,24 +227,44 @@ class ScreenUtil { | ||
195 | ///Adapt according to the smaller of width or height | 227 | ///Adapt according to the smaller of width or height |
196 | double radius(num r) => r * min(scaleWidth, scaleHeight); | 228 | double radius(num r) => r * min(scaleWidth, scaleHeight); |
197 | 229 | ||
230 | + /// Adapt according to the both width and height | ||
231 | + double diagonal(num d) => d * scaleHeight * scaleWidth; | ||
232 | + | ||
233 | + /// Adapt according to the maximum value of scale width and scale height | ||
234 | + double diameter(num d) => d * max(scaleWidth, scaleHeight); | ||
235 | + | ||
198 | ///字体大小适配方法 | 236 | ///字体大小适配方法 |
199 | ///- [fontSize] UI设计上字体的大小,单位dp. | 237 | ///- [fontSize] UI设计上字体的大小,单位dp. |
200 | ///Font size adaptation method | 238 | ///Font size adaptation method |
201 | ///- [fontSize] The size of the font on the UI design, in dp. | 239 | ///- [fontSize] The size of the font on the UI design, in dp. |
202 | - double setSp(num fontSize) => fontSize * scaleText; | 240 | + double setSp(num fontSize) => |
241 | + fontSizeResolver?.call(fontSize, _instance) ?? fontSize * scaleText; | ||
203 | 242 | ||
204 | - Widget setVerticalSpacing(num height) => SizedBox(height: setHeight(height)); | 243 | + SizedBox setVerticalSpacing(num height) => |
244 | + SizedBox(height: setHeight(height)); | ||
205 | 245 | ||
206 | - Widget setVerticalSpacingFromWidth(num height) => | 246 | + SizedBox setVerticalSpacingFromWidth(num height) => |
207 | SizedBox(height: setWidth(height)); | 247 | SizedBox(height: setWidth(height)); |
208 | 248 | ||
209 | - Widget setHorizontalSpacing(num width) => SizedBox(width: setWidth(width)); | 249 | + SizedBox setHorizontalSpacing(num width) => SizedBox(width: setWidth(width)); |
210 | 250 | ||
211 | - Widget setHorizontalSpacingRadius(num width) => | 251 | + SizedBox setHorizontalSpacingRadius(num width) => |
212 | SizedBox(width: radius(width)); | 252 | SizedBox(width: radius(width)); |
213 | 253 | ||
214 | - Widget setVerticalSpacingRadius(num height) => | 254 | + SizedBox setVerticalSpacingRadius(num height) => |
215 | SizedBox(height: radius(height)); | 255 | SizedBox(height: radius(height)); |
256 | + | ||
257 | + SizedBox setHorizontalSpacingDiameter(num width) => | ||
258 | + SizedBox(width: diameter(width)); | ||
259 | + | ||
260 | + SizedBox setVerticalSpacingDiameter(num height) => | ||
261 | + SizedBox(height: diameter(height)); | ||
262 | + | ||
263 | + SizedBox setHorizontalSpacingDiagonal(num width) => | ||
264 | + SizedBox(width: diagonal(width)); | ||
265 | + | ||
266 | + SizedBox setVerticalSpacingDiagonal(num height) => | ||
267 | + SizedBox(height: diagonal(height)); | ||
216 | } | 268 | } |
217 | 269 | ||
218 | extension on MediaQueryData? { | 270 | extension on MediaQueryData? { |
1 | +import 'dart:async'; | ||
2 | +import 'dart:collection'; | ||
3 | + | ||
1 | import 'package:flutter/widgets.dart'; | 4 | import 'package:flutter/widgets.dart'; |
5 | +import './_flutter_widgets.dart'; | ||
2 | 6 | ||
7 | +import 'screenutil_mixin.dart'; | ||
3 | import 'screen_util.dart'; | 8 | import 'screen_util.dart'; |
4 | 9 | ||
5 | typedef RebuildFactor = bool Function(MediaQueryData old, MediaQueryData data); | 10 | typedef RebuildFactor = bool Function(MediaQueryData old, MediaQueryData data); |
@@ -9,9 +14,7 @@ typedef ScreenUtilInitBuilder = Widget Function( | @@ -9,9 +14,7 @@ typedef ScreenUtilInitBuilder = Widget Function( | ||
9 | Widget? child, | 14 | Widget? child, |
10 | ); | 15 | ); |
11 | 16 | ||
12 | -class RebuildFactors { | ||
13 | - const RebuildFactors._(); | ||
14 | - | 17 | +abstract class RebuildFactors { |
15 | static bool size(MediaQueryData old, MediaQueryData data) { | 18 | static bool size(MediaQueryData old, MediaQueryData data) { |
16 | return old.size != data.size; | 19 | return old.size != data.size; |
17 | } | 20 | } |
@@ -24,35 +27,69 @@ class RebuildFactors { | @@ -24,35 +27,69 @@ class RebuildFactors { | ||
24 | return old.viewInsets != data.viewInsets; | 27 | return old.viewInsets != data.viewInsets; |
25 | } | 28 | } |
26 | 29 | ||
27 | - static bool all(MediaQueryData old, MediaQueryData data) { | 30 | + static bool change(MediaQueryData old, MediaQueryData data) { |
28 | return old != data; | 31 | return old != data; |
29 | } | 32 | } |
33 | + | ||
34 | + static bool always(MediaQueryData _, MediaQueryData __) { | ||
35 | + return true; | ||
36 | + } | ||
37 | + | ||
38 | + static bool none(MediaQueryData _, MediaQueryData __) { | ||
39 | + return false; | ||
40 | + } | ||
41 | +} | ||
42 | + | ||
43 | +abstract class FontSizeResolvers { | ||
44 | + static double width(num fontSize, ScreenUtil instance) { | ||
45 | + return instance.setWidth(fontSize); | ||
46 | + } | ||
47 | + | ||
48 | + static double height(num fontSize, ScreenUtil instance) { | ||
49 | + return instance.setHeight(fontSize); | ||
50 | + } | ||
51 | + | ||
52 | + static double raduis(num fontSize, ScreenUtil instance) { | ||
53 | + return instance.radius(fontSize); | ||
54 | + } | ||
55 | + | ||
56 | + static double diameter(num fontSize, ScreenUtil instance) { | ||
57 | + return instance.diameter(fontSize); | ||
58 | + } | ||
59 | + | ||
60 | + static double diagonal(num fontSize, ScreenUtil instance) { | ||
61 | + return instance.diagonal(fontSize); | ||
62 | + } | ||
30 | } | 63 | } |
31 | 64 | ||
32 | class ScreenUtilInit extends StatefulWidget { | 65 | class ScreenUtilInit extends StatefulWidget { |
33 | /// A helper widget that initializes [ScreenUtil] | 66 | /// A helper widget that initializes [ScreenUtil] |
34 | - const ScreenUtilInit( | ||
35 | - {Key? key, | ||
36 | - required this.builder, | 67 | + const ScreenUtilInit({ |
68 | + Key? key, | ||
69 | + this.builder, | ||
37 | this.child, | 70 | this.child, |
38 | this.rebuildFactor = RebuildFactors.size, | 71 | this.rebuildFactor = RebuildFactors.size, |
39 | this.designSize = ScreenUtil.defaultSize, | 72 | this.designSize = ScreenUtil.defaultSize, |
40 | this.splitScreenMode = false, | 73 | this.splitScreenMode = false, |
41 | this.minTextAdapt = false, | 74 | this.minTextAdapt = false, |
42 | this.useInheritedMediaQuery = false, | 75 | this.useInheritedMediaQuery = false, |
43 | - this.scaleByHeight = false}) | ||
44 | - : super(key: key); | 76 | + this.ensureScreenSize, |
77 | + this.responsiveWidgets, | ||
78 | + this.fontSizeResolver = FontSizeResolvers.width, | ||
79 | + }) : super(key: key); | ||
45 | 80 | ||
46 | - final ScreenUtilInitBuilder builder; | 81 | + final ScreenUtilInitBuilder? builder; |
47 | final Widget? child; | 82 | final Widget? child; |
48 | final bool splitScreenMode; | 83 | final bool splitScreenMode; |
49 | final bool minTextAdapt; | 84 | final bool minTextAdapt; |
50 | final bool useInheritedMediaQuery; | 85 | final bool useInheritedMediaQuery; |
51 | - final bool scaleByHeight; | 86 | + final bool? ensureScreenSize; |
52 | final RebuildFactor rebuildFactor; | 87 | final RebuildFactor rebuildFactor; |
88 | + final FontSizeResolver fontSizeResolver; | ||
53 | 89 | ||
54 | /// The [Size] of the device in the design draft, in dp | 90 | /// The [Size] of the device in the design draft, in dp |
55 | final Size designSize; | 91 | final Size designSize; |
92 | + final Iterable<String>? responsiveWidgets; | ||
56 | 93 | ||
57 | @override | 94 | @override |
58 | State<ScreenUtilInit> createState() => _ScreenUtilInitState(); | 95 | State<ScreenUtilInit> createState() => _ScreenUtilInitState(); |
@@ -60,127 +97,103 @@ class ScreenUtilInit extends StatefulWidget { | @@ -60,127 +97,103 @@ class ScreenUtilInit extends StatefulWidget { | ||
60 | 97 | ||
61 | class _ScreenUtilInitState extends State<ScreenUtilInit> | 98 | class _ScreenUtilInitState extends State<ScreenUtilInit> |
62 | with WidgetsBindingObserver { | 99 | with WidgetsBindingObserver { |
100 | + final _canMarkedToBuild = HashSet<String>(); | ||
63 | MediaQueryData? _mediaQueryData; | 101 | MediaQueryData? _mediaQueryData; |
102 | + final _binding = WidgetsBinding.instance; | ||
103 | + final _screenSizeCompleter = Completer<void>(); | ||
64 | 104 | ||
65 | - bool wrappedInMediaQuery = false; | 105 | + @override |
106 | + void initState() { | ||
107 | + if (widget.responsiveWidgets != null) { | ||
108 | + _canMarkedToBuild.addAll(widget.responsiveWidgets!); | ||
109 | + } | ||
110 | + _validateSize().then(_screenSizeCompleter.complete); | ||
111 | + | ||
112 | + super.initState(); | ||
113 | + _binding.addObserver(this); | ||
114 | + } | ||
66 | 115 | ||
67 | - WidgetsBinding get binding => WidgetsFlutterBinding.ensureInitialized(); | 116 | + @override |
117 | + void didChangeMetrics() { | ||
118 | + super.didChangeMetrics(); | ||
119 | + _revalidate(); | ||
120 | + } | ||
68 | 121 | ||
69 | - MediaQueryData get mediaQueryData => _mediaQueryData!; | 122 | + @override |
123 | + void didChangeDependencies() { | ||
124 | + super.didChangeDependencies(); | ||
125 | + _revalidate(); | ||
126 | + } | ||
70 | 127 | ||
71 | - MediaQueryData get newData { | ||
72 | - final data = MediaQuery.maybeOf(context); | 128 | + MediaQueryData? _newData() { |
129 | + MediaQueryData? mq = MediaQuery.maybeOf(context); | ||
130 | + if (mq == null) mq = MediaQueryData.fromView(View.of(context)); | ||
73 | 131 | ||
74 | - if (data != null) { | ||
75 | - if (widget.useInheritedMediaQuery) { | ||
76 | - wrappedInMediaQuery = true; | 132 | + return mq; |
77 | } | 133 | } |
78 | - return data; | 134 | + |
135 | + Future<void> _validateSize() async { | ||
136 | + if (widget.ensureScreenSize ?? false) return ScreenUtil.ensureScreenSize(); | ||
79 | } | 137 | } |
80 | 138 | ||
81 | - return MediaQueryData.fromView(View.of(context)); | 139 | + void _markNeedsBuildIfAllowed(Element el) { |
140 | + final widgetName = el.widget.runtimeType.toString(); | ||
141 | + final allowed = widget is SU || | ||
142 | + _canMarkedToBuild.contains(widgetName) || | ||
143 | + !(widgetName.startsWith('_') || flutterWidgets.contains(widgetName)); | ||
144 | + | ||
145 | + if (allowed) el.markNeedsBuild(); | ||
82 | } | 146 | } |
83 | 147 | ||
84 | - _updateTree(Element el) { | ||
85 | - el.markNeedsBuild(); | 148 | + void _updateTree(Element el) { |
149 | + _markNeedsBuildIfAllowed(el); | ||
86 | el.visitChildren(_updateTree); | 150 | el.visitChildren(_updateTree); |
87 | } | 151 | } |
88 | 152 | ||
89 | - @override | ||
90 | - void initState() { | ||
91 | - super.initState(); | ||
92 | - binding.addObserver(this); | ||
93 | - } | 153 | + void _revalidate([void Function()? callback]) { |
154 | + final oldData = _mediaQueryData; | ||
155 | + final newData = _newData(); | ||
94 | 156 | ||
95 | - @override | ||
96 | - void didChangeMetrics() { | ||
97 | - final old = _mediaQueryData!; | ||
98 | - final data = newData; | 157 | + if (newData == null) return; |
99 | 158 | ||
100 | - if (widget.scaleByHeight || widget.rebuildFactor(old, data)) { | ||
101 | - _mediaQueryData = data; | 159 | + if (oldData == null || widget.rebuildFactor(oldData, newData)) { |
160 | + setState(() { | ||
161 | + _mediaQueryData = newData; | ||
102 | _updateTree(context as Element); | 162 | _updateTree(context as Element); |
163 | + callback?.call(); | ||
164 | + }); | ||
103 | } | 165 | } |
104 | } | 166 | } |
105 | 167 | ||
106 | @override | 168 | @override |
107 | - void didChangeDependencies() { | ||
108 | - super.didChangeDependencies(); | ||
109 | - if (_mediaQueryData == null) _mediaQueryData = newData; | ||
110 | - didChangeMetrics(); | ||
111 | - } | 169 | + Widget build(BuildContext context) { |
170 | + final mq = _mediaQueryData; | ||
112 | 171 | ||
113 | - @override | ||
114 | - void dispose() { | ||
115 | - binding.removeObserver(this); | ||
116 | - super.dispose(); | ||
117 | - } | 172 | + if (mq == null) return const SizedBox.shrink(); |
118 | 173 | ||
119 | - @override | ||
120 | - Widget build(BuildContext _context) { | ||
121 | - if (mediaQueryData.size == Size.zero) return const SizedBox.shrink(); | ||
122 | - if (!wrappedInMediaQuery) { | ||
123 | - return MediaQuery( | ||
124 | - data: mediaQueryData, | ||
125 | - child: Builder( | ||
126 | - builder: (__context) { | ||
127 | - ScreenUtil.init( | ||
128 | - __context, | 174 | + return FutureBuilder<void>( |
175 | + future: _screenSizeCompleter.future, | ||
176 | + builder: (c, snapshot) { | ||
177 | + ScreenUtil.configure( | ||
178 | + data: mq, | ||
129 | designSize: widget.designSize, | 179 | designSize: widget.designSize, |
130 | splitScreenMode: widget.splitScreenMode, | 180 | splitScreenMode: widget.splitScreenMode, |
131 | minTextAdapt: widget.minTextAdapt, | 181 | minTextAdapt: widget.minTextAdapt, |
132 | - scaleByHeight: widget.scaleByHeight, | ||
133 | - ); | ||
134 | - final deviceData = MediaQuery.maybeOf(__context); | ||
135 | - final deviceSize = deviceData?.size ?? widget.designSize; | ||
136 | - return MediaQuery( | ||
137 | - data: MediaQueryData.fromView(View.of(__context)), | ||
138 | - child: Container( | ||
139 | - width: deviceSize.width, | ||
140 | - height: deviceSize.height, | ||
141 | - child: FittedBox( | ||
142 | - fit: BoxFit.none, | ||
143 | - alignment: Alignment.center, | ||
144 | - child: Container( | ||
145 | - width: widget.scaleByHeight | ||
146 | - ? (deviceSize.height * widget.designSize.width) / | ||
147 | - widget.designSize.height | ||
148 | - : deviceSize.width, | ||
149 | - height: deviceSize.height, | ||
150 | - child: widget.builder(__context, widget.child), | ||
151 | - ), | ||
152 | - ), | ||
153 | - ), | 182 | + fontSizeResolver: widget.fontSizeResolver, |
154 | ); | 183 | ); |
184 | + | ||
185 | + if (snapshot.connectionState == ConnectionState.done) { | ||
186 | + return widget.builder?.call(context, widget.child) ?? widget.child!; | ||
187 | + } | ||
188 | + | ||
189 | + return const SizedBox.shrink(); | ||
155 | }, | 190 | }, |
156 | - ), | ||
157 | ); | 191 | ); |
158 | } | 192 | } |
159 | 193 | ||
160 | - ScreenUtil.init( | ||
161 | - _context, | ||
162 | - designSize: widget.designSize, | ||
163 | - splitScreenMode: widget.splitScreenMode, | ||
164 | - minTextAdapt: widget.minTextAdapt, | ||
165 | - scaleByHeight: widget.scaleByHeight, | ||
166 | - ); | ||
167 | - final deviceData = MediaQuery.maybeOf(_context); | ||
168 | - final deviceSize = deviceData?.size ?? widget.designSize; | ||
169 | - return Container( | ||
170 | - width: deviceSize.width, | ||
171 | - height: deviceSize.height, | ||
172 | - child: FittedBox( | ||
173 | - fit: BoxFit.none, | ||
174 | - alignment: Alignment.center, | ||
175 | - child: Container( | ||
176 | - width: widget.scaleByHeight | ||
177 | - ? (deviceSize.height * widget.designSize.width) / | ||
178 | - widget.designSize.height | ||
179 | - : deviceSize.width, | ||
180 | - height: deviceSize.height, | ||
181 | - child: widget.builder(_context, widget.child), | ||
182 | - ), | ||
183 | - ), | ||
184 | - ); | 194 | + @override |
195 | + void dispose() { | ||
196 | + _binding.removeObserver(this); | ||
197 | + super.dispose(); | ||
185 | } | 198 | } |
186 | } | 199 | } |
lib/src/screenutil_mixin.dart
0 → 100644
@@ -14,6 +14,12 @@ extension SizeExtension on num { | @@ -14,6 +14,12 @@ extension SizeExtension on num { | ||
14 | ///[ScreenUtil.radius] | 14 | ///[ScreenUtil.radius] |
15 | double get r => ScreenUtil().radius(this); | 15 | double get r => ScreenUtil().radius(this); |
16 | 16 | ||
17 | + ///[ScreenUtil.diagonal] | ||
18 | + double get dg => ScreenUtil().diagonal(this); | ||
19 | + | ||
20 | + ///[ScreenUtil.diameter] | ||
21 | + double get dm => ScreenUtil().diameter(this); | ||
22 | + | ||
17 | ///[ScreenUtil.setSp] | 23 | ///[ScreenUtil.setSp] |
18 | double get sp => ScreenUtil().setSp(this); | 24 | double get sp => ScreenUtil().setSp(this); |
19 | 25 | ||
@@ -36,22 +42,38 @@ extension SizeExtension on num { | @@ -36,22 +42,38 @@ extension SizeExtension on num { | ||
36 | double get sh => ScreenUtil().screenHeight * this; | 42 | double get sh => ScreenUtil().screenHeight * this; |
37 | 43 | ||
38 | ///[ScreenUtil.setHeight] | 44 | ///[ScreenUtil.setHeight] |
39 | - Widget get verticalSpace => ScreenUtil().setVerticalSpacing(this); | 45 | + SizedBox get verticalSpace => ScreenUtil().setVerticalSpacing(this); |
40 | 46 | ||
41 | ///[ScreenUtil.setVerticalSpacingFromWidth] | 47 | ///[ScreenUtil.setVerticalSpacingFromWidth] |
42 | - Widget get verticalSpaceFromWidth => | 48 | + SizedBox get verticalSpaceFromWidth => |
43 | ScreenUtil().setVerticalSpacingFromWidth(this); | 49 | ScreenUtil().setVerticalSpacingFromWidth(this); |
44 | 50 | ||
45 | ///[ScreenUtil.setWidth] | 51 | ///[ScreenUtil.setWidth] |
46 | - Widget get horizontalSpace => ScreenUtil().setHorizontalSpacing(this); | 52 | + SizedBox get horizontalSpace => ScreenUtil().setHorizontalSpacing(this); |
47 | 53 | ||
48 | ///[ScreenUtil.radius] | 54 | ///[ScreenUtil.radius] |
49 | - Widget get horizontalSpaceRadius => | 55 | + SizedBox get horizontalSpaceRadius => |
50 | ScreenUtil().setHorizontalSpacingRadius(this); | 56 | ScreenUtil().setHorizontalSpacingRadius(this); |
51 | 57 | ||
52 | ///[ScreenUtil.radius] | 58 | ///[ScreenUtil.radius] |
53 | - Widget get verticalSpacingRadius => | 59 | + SizedBox get verticalSpacingRadius => |
54 | ScreenUtil().setVerticalSpacingRadius(this); | 60 | ScreenUtil().setVerticalSpacingRadius(this); |
61 | + | ||
62 | + ///[ScreenUtil.diameter] | ||
63 | + SizedBox get horizontalSpaceDiameter => | ||
64 | + ScreenUtil().setHorizontalSpacingDiameter(this); | ||
65 | + | ||
66 | + ///[ScreenUtil.diameter] | ||
67 | + SizedBox get verticalSpacingDiameter => | ||
68 | + ScreenUtil().setVerticalSpacingDiameter(this); | ||
69 | + | ||
70 | + ///[ScreenUtil.diagonal] | ||
71 | + SizedBox get horizontalSpaceDiagonal => | ||
72 | + ScreenUtil().setHorizontalSpacingDiagonal(this); | ||
73 | + | ||
74 | + ///[ScreenUtil.diagonal] | ||
75 | + SizedBox get verticalSpacingDiagonal => | ||
76 | + ScreenUtil().setVerticalSpacingDiagonal(this); | ||
55 | } | 77 | } |
56 | 78 | ||
57 | extension EdgeInsetsExtension on EdgeInsets { | 79 | extension EdgeInsetsExtension on EdgeInsets { |
@@ -63,6 +85,20 @@ extension EdgeInsetsExtension on EdgeInsets { | @@ -63,6 +85,20 @@ extension EdgeInsetsExtension on EdgeInsets { | ||
63 | left: left.r, | 85 | left: left.r, |
64 | ); | 86 | ); |
65 | 87 | ||
88 | + EdgeInsets get dm => copyWith( | ||
89 | + top: top.dm, | ||
90 | + bottom: bottom.dm, | ||
91 | + right: right.dm, | ||
92 | + left: left.dm, | ||
93 | + ); | ||
94 | + | ||
95 | + EdgeInsets get dg => copyWith( | ||
96 | + top: top.dg, | ||
97 | + bottom: bottom.dg, | ||
98 | + right: right.dg, | ||
99 | + left: left.dg, | ||
100 | + ); | ||
101 | + | ||
66 | EdgeInsets get w => copyWith( | 102 | EdgeInsets get w => copyWith( |
67 | top: top.w, | 103 | top: top.w, |
68 | bottom: bottom.w, | 104 | bottom: bottom.w, |
@@ -106,6 +142,10 @@ extension RaduisExtension on Radius { | @@ -106,6 +142,10 @@ extension RaduisExtension on Radius { | ||
106 | /// Creates adapt Radius using r [SizeExtension]. | 142 | /// Creates adapt Radius using r [SizeExtension]. |
107 | Radius get r => Radius.elliptical(x.r, y.r); | 143 | Radius get r => Radius.elliptical(x.r, y.r); |
108 | 144 | ||
145 | + Radius get dm => Radius.elliptical(x.dm, y.dm); | ||
146 | + | ||
147 | + Radius get dg => Radius.elliptical(x.dg, y.dg); | ||
148 | + | ||
109 | Radius get w => Radius.elliptical(x.w, y.w); | 149 | Radius get w => Radius.elliptical(x.w, y.w); |
110 | 150 | ||
111 | Radius get h => Radius.elliptical(x.h, y.h); | 151 | Radius get h => Radius.elliptical(x.h, y.h); |
1 | name: flutter_screenutil | 1 | name: flutter_screenutil |
2 | description: A flutter plugin for adapting screen and font size.Guaranteed to look good on different models | 2 | description: A flutter plugin for adapting screen and font size.Guaranteed to look good on different models |
3 | -version: 5.8.4 | 3 | +version: 5.9.0-beta |
4 | homepage: https://github.com/OpenFlutter/flutter_screenutil | 4 | homepage: https://github.com/OpenFlutter/flutter_screenutil |
5 | 5 | ||
6 | environment: | 6 | environment: |
7 | - sdk: ">=2.12.0 <4.0.0" | 7 | + sdk: ">=2.17.0 <4.0.0" |
8 | flutter: ">=3.10.0" | 8 | flutter: ">=3.10.0" |
9 | 9 | ||
10 | dependencies: | 10 | dependencies: |
test/flutter_screenutil_test.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
3 | +import 'package:flutter_test/flutter_test.dart'; | ||
4 | + | ||
5 | +import 'home.test.dart'; | ||
6 | + | ||
7 | +void main() { | ||
8 | + const smallerDeviceSize = Size(300, 600); | ||
9 | + const smallerDeviceData = MediaQueryData(size: smallerDeviceSize); | ||
10 | + | ||
11 | + const biggerDeviceSize = Size(500, 900); | ||
12 | + const biggerDeviceData = MediaQueryData(size: biggerDeviceSize); | ||
13 | + | ||
14 | + const uiSize = Size(470, 740); | ||
15 | + | ||
16 | + group('[Test calculations]', () { | ||
17 | + test('Test smaller size', () { | ||
18 | + ScreenUtil.configure( | ||
19 | + data: smallerDeviceData, | ||
20 | + designSize: uiSize, | ||
21 | + minTextAdapt: true, | ||
22 | + splitScreenMode: false, | ||
23 | + ); | ||
24 | + | ||
25 | + expect(1.w, smallerDeviceSize.width / uiSize.width); | ||
26 | + expect(1.w < 1, true); | ||
27 | + expect(1.h, smallerDeviceSize.height / uiSize.height); | ||
28 | + expect(1.h < 1, true); | ||
29 | + }); | ||
30 | + | ||
31 | + test('Test bigger size', () { | ||
32 | + ScreenUtil.configure( | ||
33 | + data: biggerDeviceData, | ||
34 | + designSize: uiSize, | ||
35 | + minTextAdapt: true, | ||
36 | + splitScreenMode: false, | ||
37 | + ); | ||
38 | + | ||
39 | + expect(1.w, biggerDeviceSize.width / uiSize.width); | ||
40 | + expect(1.w > 1, true); | ||
41 | + expect(1.h, biggerDeviceSize.height / uiSize.height); | ||
42 | + expect(1.h > 1, true); | ||
43 | + }); | ||
44 | + }); | ||
45 | + | ||
46 | + group('[Test overflow]', () { | ||
47 | + testWidgets('Test overflow width', (tester) async { | ||
48 | + await tester.pumpWidget(ScreenUtilInit( | ||
49 | + designSize: uiSize, | ||
50 | + child: MaterialApp(home: WidgetTest(width: () => uiSize.width.w)), | ||
51 | + )); | ||
52 | + | ||
53 | + // Wait until all widget rendered | ||
54 | + await tester.pumpAndSettle(); | ||
55 | + | ||
56 | + // a Text widget must be present | ||
57 | + expect(find.text('Test'), findsOneWidget); | ||
58 | + }); | ||
59 | + | ||
60 | + testWidgets('Test overflow height', (tester) async { | ||
61 | + await tester.pumpWidget(ScreenUtilInit( | ||
62 | + designSize: uiSize, | ||
63 | + child: MaterialApp(home: WidgetTest(height: () => uiSize.height.h)), | ||
64 | + )); | ||
65 | + | ||
66 | + // Wait until all widget rendered | ||
67 | + await tester.pumpAndSettle(); | ||
68 | + | ||
69 | + // a Text widget must be present | ||
70 | + expect(find.text('Test'), findsOneWidget); | ||
71 | + }); | ||
72 | + }); | ||
73 | + | ||
74 | + testWidgets('[Rebuilding]', (tester) async { | ||
75 | + final textFieldKey = UniqueKey(); | ||
76 | + final buildCountNotifier = ValueNotifier(0); | ||
77 | + final focusNode = FocusNode(); | ||
78 | + | ||
79 | + Finder textField() => find.byKey(textFieldKey); | ||
80 | + | ||
81 | + await tester.pumpWidget(ScreenUtilInit( | ||
82 | + designSize: uiSize, | ||
83 | + rebuildFactor: RebuildFactors.always, | ||
84 | + child: MaterialApp( | ||
85 | + home: Scaffold( | ||
86 | + body: Builder( | ||
87 | + builder: (context) { | ||
88 | + buildCountNotifier.value += 1; | ||
89 | + | ||
90 | + assert(uiSize.width.w == MediaQuery.of(context).size.width); | ||
91 | + | ||
92 | + return SizedBox( | ||
93 | + width: 1.sw, | ||
94 | + child: Column( | ||
95 | + children: [ | ||
96 | + ValueListenableBuilder<int>( | ||
97 | + valueListenable: buildCountNotifier, | ||
98 | + builder: (_, count, __) => Text('Built count: $count'), | ||
99 | + ), | ||
100 | + TextField( | ||
101 | + key: textFieldKey, | ||
102 | + focusNode: focusNode, | ||
103 | + ), | ||
104 | + ], | ||
105 | + ), | ||
106 | + ); | ||
107 | + }, | ||
108 | + ), | ||
109 | + ), | ||
110 | + ), | ||
111 | + )); | ||
112 | + | ||
113 | + await tester.pumpAndSettle(); | ||
114 | + expect(buildCountNotifier.value, 1); | ||
115 | + | ||
116 | + expect(textField(), findsOneWidget); | ||
117 | + expect(focusNode.hasFocus, false); | ||
118 | + | ||
119 | + await tester.tap(textField()).then((_) => tester.pumpAndSettle()); | ||
120 | + expect(textField(), findsOneWidget); | ||
121 | + expect(focusNode.hasFocus, true); | ||
122 | + expect(buildCountNotifier.value, 1); | ||
123 | + | ||
124 | + // Simulate keyboard | ||
125 | + tester.view.viewInsets = FakeViewPadding(bottom: 20); | ||
126 | + | ||
127 | + await tester.pumpAndSettle(); | ||
128 | + expect(focusNode.hasFocus, true); | ||
129 | + expect(buildCountNotifier.value, 1); | ||
130 | + }); | ||
131 | +} |
test/home.test.dart
0 → 100644
1 | +import 'package:flutter/widgets.dart'; | ||
2 | + | ||
3 | +class WidgetTest extends StatelessWidget { | ||
4 | + const WidgetTest({ | ||
5 | + super.key, | ||
6 | + this.width = _zero, | ||
7 | + this.height = _zero, | ||
8 | + }); | ||
9 | + | ||
10 | + final double Function() width; | ||
11 | + final double Function() height; | ||
12 | + | ||
13 | + @override | ||
14 | + Widget build(BuildContext context) { | ||
15 | + return LayoutBuilder( | ||
16 | + builder: (_, c) { | ||
17 | + final w = width(), h = height(); | ||
18 | + | ||
19 | + if (c.biggest >= Size(w, h)) { | ||
20 | + return const Text('Test'); | ||
21 | + } | ||
22 | + | ||
23 | + throw Error(); | ||
24 | + }, | ||
25 | + ); | ||
26 | + } | ||
27 | + | ||
28 | + static double _zero() => 0; | ||
29 | +} |
-
Please register or login to post a comment