Mounir-Bouaiche

Fix #362 & add BuildContext to builder parameters

@@ -9,9 +9,8 @@ class MyApp extends StatelessWidget { @@ -9,9 +9,8 @@ class MyApp extends StatelessWidget {
9 Widget build(BuildContext context) { 9 Widget build(BuildContext context) {
10 // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it 10 // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it
11 return ScreenUtilInit( 11 return ScreenUtilInit(
12 - builder: (child) { 12 + builder: (_, child) {
13 return MaterialApp( 13 return MaterialApp(
14 - key: const GlobalObjectKey('screen-util'),  
15 debugShowCheckedModeBanner: false, 14 debugShowCheckedModeBanner: false,
16 title: 'First Method', 15 title: 'First Method',
17 // You can use the library anywhere in the app even in theme 16 // You can use the library anywhere in the app even in theme
@@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; @@ -3,7 +3,7 @@ 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 {
6 - const HomePageScaffold({Key? key, required this.title}) : super(key: key); 6 + const HomePageScaffold({Key? key, this.title = ''}) : super(key: key);
7 7
8 void printScreenInformation() { 8 void printScreenInformation() {
9 print('Device Size:${Size(1.sw, 1.sh)}'); 9 print('Device Size:${Size(1.sw, 1.sh)}');
@@ -114,9 +114,7 @@ class HomePageScaffold extends StatelessWidget { @@ -114,9 +114,7 @@ class HomePageScaffold extends StatelessWidget {
114 onPressed: () { 114 onPressed: () {
115 Navigator.of(context).push( 115 Navigator.of(context).push(
116 MaterialPageRoute(builder: (context) { 116 MaterialPageRoute(builder: (context) {
117 - return ScreenUtilInit(builder: (context) {  
118 - return HomePageScaffold(title: title);  
119 - }); 117 + return const HomePageScaffold();
120 }), 118 }),
121 ); 119 );
122 }, 120 },
@@ -9,7 +9,7 @@ class MyApp extends StatelessWidget { @@ -9,7 +9,7 @@ class MyApp extends StatelessWidget {
9 Widget build(BuildContext context) { 9 Widget build(BuildContext context) {
10 // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it 10 // In first method you only need to wrap [MaterialApp] with [ScreenUtilInit] and that's it
11 return ScreenUtilInit( 11 return ScreenUtilInit(
12 - builder: (child) { 12 + builder: (_, child) {
13 return MaterialApp( 13 return MaterialApp(
14 debugShowCheckedModeBanner: false, 14 debugShowCheckedModeBanner: false,
15 title: '第一种方法', 15 title: '第一种方法',
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 5
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 import 'dart:ui' show FlutterWindow; 7 import 'dart:ui' show FlutterWindow;
  8 +import 'dart:async' show Completer;
8 9
9 import 'package:flutter/widgets.dart'; 10 import 'package:flutter/widgets.dart';
10 11
@@ -78,10 +79,8 @@ class ScreenUtil { @@ -78,10 +79,8 @@ class ScreenUtil {
78 BuildContext context, [ 79 BuildContext context, [
79 bool withDescendants = false, 80 bool withDescendants = false,
80 ]) { 81 ]) {
81 - final instance = ScreenUtil();  
82 - (instance._elementsToRebuild ??= {}).add(context as Element); 82 + (_instance._elementsToRebuild ??= {}).add(context as Element);
83 83
84 - // MediaQuery.maybeOf(context);  
85 if (withDescendants) { 84 if (withDescendants) {
86 context.visitChildren((element) { 85 context.visitChildren((element) {
87 registerToBuild(element, true); 86 registerToBuild(element, true);
@@ -90,25 +89,27 @@ class ScreenUtil { @@ -90,25 +89,27 @@ class ScreenUtil {
90 } 89 }
91 90
92 /// Initializing the library. 91 /// Initializing the library.
93 - static void init(  
94 - BuildContext? context, {  
95 - Orientation? orientation,  
96 - Size? deviceSize, 92 + static Future<void> init(
  93 + BuildContext context, {
97 Size designSize = defaultSize, 94 Size designSize = defaultSize,
98 bool splitScreenMode = false, 95 bool splitScreenMode = false,
99 bool minTextAdapt = false, 96 bool minTextAdapt = false,
100 - }) { 97 + }) async {
  98 + final navigatorContext = Navigator.maybeOf(context)?.context as Element?;
101 final mediaQueryContext = 99 final mediaQueryContext =
102 - context?.getElementForInheritedWidgetOfExactType<MediaQuery>(); 100 + navigatorContext?.getElementForInheritedWidgetOfExactType<MediaQuery>();
103 101
104 - final deviceData = mediaQueryContext != null  
105 - ? MediaQuery.of(context!).nonEmptySizeOrNull()  
106 - : null; 102 + final initCompleter = Completer<void>();
107 103
108 - mediaQueryContext?.visitChildren((el) => context = el); 104 + WidgetsBinding.instance.addPostFrameCallback((_) {
  105 + mediaQueryContext?.visitChildElements((el) => _instance._context = el);
  106 + if (_instance._context != null) initCompleter.complete();
  107 + });
109 108
110 - deviceSize ??= deviceData?.size ?? designSize;  
111 - orientation ??= deviceData?.orientation ?? 109 + final deviceData = MediaQuery.maybeOf(context).nonEmptySizeOrNull();
  110 +
  111 + final deviceSize = deviceData?.size ?? designSize;
  112 + final orientation = deviceData?.orientation ??
112 (deviceSize.width > deviceSize.height 113 (deviceSize.width > deviceSize.height
113 ? Orientation.landscape 114 ? Orientation.landscape
114 : Orientation.portrait); 115 : Orientation.portrait);
@@ -119,10 +120,11 @@ class ScreenUtil { @@ -119,10 +120,11 @@ class ScreenUtil {
119 .._minTextAdapt = minTextAdapt 120 .._minTextAdapt = minTextAdapt
120 .._orientation = orientation 121 .._orientation = orientation
121 .._screenWidth = deviceSize.width 122 .._screenWidth = deviceSize.width
122 - .._screenHeight = deviceSize.height  
123 - .._context = context; 123 + .._screenHeight = deviceSize.height;
124 124
125 _instance._elementsToRebuild?.forEach((el) => el.markNeedsBuild()); 125 _instance._elementsToRebuild?.forEach((el) => el.markNeedsBuild());
  126 +
  127 + return initCompleter.future;
126 } 128 }
127 129
128 ///获取屏幕方向 130 ///获取屏幕方向
@@ -4,26 +4,45 @@ import 'screen_util.dart'; @@ -4,26 +4,45 @@ import 'screen_util.dart';
4 4
5 typedef RebuildFactor = bool Function(MediaQueryData old, MediaQueryData data); 5 typedef RebuildFactor = bool Function(MediaQueryData old, MediaQueryData data);
6 6
7 -bool defaultRebuildFactor(old, data) => old.size != data.size; 7 +typedef ScreenUtilInitBuilder = Widget Function(
  8 + BuildContext context,
  9 + Widget? child,
  10 +);
  11 +
  12 +class RebuildFactors {
  13 + const RebuildFactors._();
  14 +
  15 + static bool size(MediaQueryData old, MediaQueryData data) {
  16 + return old.size != data.size;
  17 + }
  18 +
  19 + static bool orientation(MediaQueryData old, MediaQueryData data) {
  20 + return old.orientation != data.orientation;
  21 + }
  22 +
  23 + static bool sizeAndViewInsets(MediaQueryData old, MediaQueryData data) {
  24 + return old.viewInsets != data.viewInsets;
  25 + }
  26 +
  27 + static bool all(MediaQueryData old, MediaQueryData data) {
  28 + return old != data;
  29 + }
  30 +}
8 31
9 class ScreenUtilInit extends StatefulWidget { 32 class ScreenUtilInit extends StatefulWidget {
10 /// A helper widget that initializes [ScreenUtil] 33 /// A helper widget that initializes [ScreenUtil]
11 const ScreenUtilInit({ 34 const ScreenUtilInit({
12 Key? key, 35 Key? key,
13 - this.builder, 36 + required this.builder,
14 this.child, 37 this.child,
15 - this.rebuildFactor = defaultRebuildFactor, 38 + this.rebuildFactor = RebuildFactors.size,
16 this.designSize = ScreenUtil.defaultSize, 39 this.designSize = ScreenUtil.defaultSize,
17 this.splitScreenMode = false, 40 this.splitScreenMode = false,
18 this.minTextAdapt = false, 41 this.minTextAdapt = false,
19 this.useInheritedMediaQuery = false, 42 this.useInheritedMediaQuery = false,
20 - }) : assert(  
21 - builder != null || child != null,  
22 - 'You must either pass builder or child or both',  
23 - ),  
24 - super(key: key); 43 + }) : super(key: key);
25 44
26 - final Widget Function(Widget? child)? builder; 45 + final ScreenUtilInitBuilder builder;
27 final Widget? child; 46 final Widget? child;
28 final bool splitScreenMode; 47 final bool splitScreenMode;
29 final bool minTextAdapt; 48 final bool minTextAdapt;
@@ -40,6 +59,7 @@ class ScreenUtilInit extends StatefulWidget { @@ -40,6 +59,7 @@ class ScreenUtilInit extends StatefulWidget {
40 class _ScreenUtilInitState extends State<ScreenUtilInit> 59 class _ScreenUtilInitState extends State<ScreenUtilInit>
41 with WidgetsBindingObserver { 60 with WidgetsBindingObserver {
42 late MediaQueryData mediaQueryData; 61 late MediaQueryData mediaQueryData;
  62 +
43 bool wrappedInMediaQuery = false; 63 bool wrappedInMediaQuery = false;
44 64
45 WidgetsBinding get binding => WidgetsFlutterBinding.ensureInitialized(); 65 WidgetsBinding get binding => WidgetsFlutterBinding.ensureInitialized();
@@ -60,16 +80,12 @@ class _ScreenUtilInitState extends State<ScreenUtilInit> @@ -60,16 +80,12 @@ class _ScreenUtilInitState extends State<ScreenUtilInit>
60 } 80 }
61 81
62 Widget get child { 82 Widget get child {
63 - return SizedBox(  
64 - key: GlobalObjectKey(  
65 - hashValues(  
66 - this,  
67 - mediaQueryData.size.width,  
68 - mediaQueryData.size.height,  
69 - ),  
70 - ),  
71 - child: widget.builder?.call(widget.child) ?? widget.child!,  
72 - ); 83 + return widget.builder.call(context, widget.child);
  84 + }
  85 +
  86 + _updateTree(Element el) {
  87 + el.markNeedsBuild();
  88 + el.visitChildren(_updateTree);
73 } 89 }
74 90
75 @override 91 @override
@@ -84,7 +100,10 @@ class _ScreenUtilInitState extends State<ScreenUtilInit> @@ -84,7 +100,10 @@ class _ScreenUtilInitState extends State<ScreenUtilInit>
84 final old = mediaQueryData; 100 final old = mediaQueryData;
85 final data = newData; 101 final data = newData;
86 102
87 - if (widget.rebuildFactor(old, data)) setState(() => mediaQueryData = data); 103 + if (widget.rebuildFactor(old, data)) {
  104 + mediaQueryData = data;
  105 + _updateTree(context as Element);
  106 + }
88 } 107 }
89 108
90 @override 109 @override