Skip to content

Commit 2354f30

Browse files
committed
update
1 parent a8cd013 commit 2354f30

15 files changed

Lines changed: 311 additions & 80 deletions

lib/src/_hidden/image_painter.dart

Lines changed: 0 additions & 54 deletions
This file was deleted.

lib/src/_src.g.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
88
//.title~
99

10+
export 'adaptive_layout_builder.dart';
1011
export './screen_bread_crumb_bar.dart';
1112
export './screen_states/adaptive_screen_state/mixins/default_padding_screen_mixin.dart';
1213
export './screen_states/adaptive_screen_state/mixins/default_scrollable_align_screen_mixin.dart';
@@ -18,4 +19,4 @@ export './screen_states/adaptive_screen_state/adaptive_screen_state.dart';
1819
export './screen_controller.dart';
1920
export './screen_state.dart';
2021
export './app_layout.dart';
21-
export './screen.dart';
22+
export './screen.dart';
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//.title~
99

1010
export './view_insets_builder.dart';
11-
export './image_painter.dart';
1211
export './current_platform.dart';
1312
export './screen_calculator.dart';
14-
export './surface.dart';
13+
export './surface.dart';
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
import 'package:flutter/material.dart';
2+
3+
import '_src.g.dart';
4+
import 'package:df_type/df_type.dart' show letAsOrNull;
5+
6+
/// A widget that adapts its layout based on screen size and orientation using AppLayout.
7+
/// Supports WIDE, NARROW, MOBILE_HORIZONTAL, and MOBILE layouts, compatible with AdaptiveScreenStateInterface.
8+
class AdaptiveLayoutBuilder extends StatelessWidget {
9+
/// Builder for the main content body
10+
final Widget Function(BuildContext) bodyBuilder;
11+
12+
/// Optional builders for specific layouts
13+
final Widget Function(BuildContext, Widget)? mobileLayoutBuilder;
14+
final Widget Function(BuildContext, Widget)? horizontalMobileLayoutBuilder;
15+
final Widget Function(BuildContext, Widget)? narrowLayoutBuilder;
16+
final Widget Function(BuildContext, Widget)? wideLayoutBuilder;
17+
18+
/// Optional builders for specific body content
19+
final Widget Function(BuildContext)? mobileBodyBuilder;
20+
final Widget Function(BuildContext)? horizontalMobileBodyBuilder;
21+
final Widget Function(BuildContext)? narrowBodyBuilder;
22+
final Widget Function(BuildContext)? wideBodyBuilder;
23+
24+
/// Optional side widgets
25+
final Widget Function(BuildContext, double)? topSideBuilder;
26+
final Widget Function(BuildContext, double)? bottomSideBuilder;
27+
final Widget Function(BuildContext, double)? leftSideBuilder;
28+
final Widget Function(BuildContext, double)? rightSideBuilder;
29+
30+
/// Optional background and foreground
31+
final Widget Function(BuildContext)? backgroundBuilder;
32+
final Widget Function(BuildContext)? foregroundBuilder;
33+
34+
/// Padding for the body
35+
final Widget Function(BuildContext, Widget)? paddingBuilder;
36+
37+
/// Alignment for the body with side insets
38+
final Widget Function(BuildContext, Widget, EdgeInsets)? alignBuilder;
39+
40+
/// Presentation of body, background, and foreground
41+
final Widget Function(BuildContext, Widget, Widget, Widget)? presentationBuilder;
42+
43+
/// Side insets calculation
44+
final EdgeInsets Function(BuildContext, EdgeInsets)? sideInsetsBuilder;
45+
46+
const AdaptiveLayoutBuilder({
47+
super.key,
48+
required this.bodyBuilder,
49+
this.mobileLayoutBuilder,
50+
this.horizontalMobileLayoutBuilder,
51+
this.narrowLayoutBuilder,
52+
this.wideLayoutBuilder,
53+
this.mobileBodyBuilder,
54+
this.horizontalMobileBodyBuilder,
55+
this.narrowBodyBuilder,
56+
this.wideBodyBuilder,
57+
this.topSideBuilder,
58+
this.bottomSideBuilder,
59+
this.leftSideBuilder,
60+
this.rightSideBuilder,
61+
this.backgroundBuilder,
62+
this.foregroundBuilder,
63+
this.paddingBuilder,
64+
this.alignBuilder,
65+
this.presentationBuilder,
66+
this.sideInsetsBuilder,
67+
});
68+
69+
@override
70+
Widget build(BuildContext context) {
71+
return LayoutBuilder(
72+
builder: (context, constraints) {
73+
final layoutType = AppLayout.currentScreenLayout();
74+
75+
// Build the appropriate body based on layout type
76+
var body = _buildBody(context, layoutType);
77+
78+
// Apply padding
79+
body = paddingBuilder?.call(context, body) ?? body;
80+
81+
// Build side widgets
82+
final topSide = topSideBuilder?.call(context, MediaQuery.of(context).viewInsets.top) ??
83+
const SizedBox.shrink();
84+
final bottomSide =
85+
bottomSideBuilder?.call(context, MediaQuery.of(context).viewInsets.bottom) ??
86+
const SizedBox.shrink();
87+
final leftSide = leftSideBuilder?.call(context, MediaQuery.of(context).viewInsets.left) ??
88+
const SizedBox.shrink();
89+
final rightSide =
90+
rightSideBuilder?.call(context, MediaQuery.of(context).viewInsets.right) ??
91+
const SizedBox.shrink();
92+
93+
// Calculate side insets
94+
final sideInsets = sideInsetsBuilder?.call(
95+
context,
96+
EdgeInsets.only(
97+
left: letAsOrNull<PreferredSizeWidget>(leftSide)?.preferredSize.width ?? 0.0,
98+
right: letAsOrNull<PreferredSizeWidget>(rightSide)?.preferredSize.width ?? 0.0,
99+
top: letAsOrNull<PreferredSizeWidget>(topSide)?.preferredSize.height ?? 0.0,
100+
bottom: letAsOrNull<PreferredSizeWidget>(bottomSide)?.preferredSize.height ?? 0.0,
101+
),
102+
) ??
103+
EdgeInsets.zero;
104+
105+
// Align body with side insets
106+
body = alignBuilder?.call(context, body, sideInsets) ??
107+
_defaultAlign(context, body, sideInsets);
108+
109+
// Combine body with side widgets
110+
body = Stack(
111+
alignment: AlignmentDirectional.center,
112+
fit: StackFit.expand,
113+
children: [
114+
body,
115+
Column(
116+
mainAxisSize: MainAxisSize.max,
117+
mainAxisAlignment: MainAxisAlignment.center,
118+
crossAxisAlignment: CrossAxisAlignment.center,
119+
children: [
120+
topSide is PreferredSizeWidget
121+
? ConstrainedBox(
122+
constraints: BoxConstraints.loose(topSide.preferredSize),
123+
child: topSide,
124+
)
125+
: topSide,
126+
Expanded(
127+
child: Row(
128+
mainAxisSize: MainAxisSize.max,
129+
mainAxisAlignment: MainAxisAlignment.center,
130+
crossAxisAlignment: CrossAxisAlignment.center,
131+
children: [
132+
leftSide is PreferredSizeWidget
133+
? ConstrainedBox(
134+
constraints: BoxConstraints.loose(leftSide.preferredSize),
135+
child: leftSide,
136+
)
137+
: leftSide,
138+
const Spacer(),
139+
rightSide is PreferredSizeWidget
140+
? ConstrainedBox(
141+
constraints: BoxConstraints.loose(rightSide.preferredSize),
142+
child: rightSide,
143+
)
144+
: rightSide,
145+
],
146+
),
147+
),
148+
bottomSide is PreferredSizeWidget
149+
? ConstrainedBox(
150+
constraints: BoxConstraints.loose(bottomSide.preferredSize),
151+
child: bottomSide,
152+
)
153+
: bottomSide,
154+
],
155+
),
156+
],
157+
);
158+
159+
// Apply presentation
160+
body = presentationBuilder?.call(
161+
context,
162+
body,
163+
backgroundBuilder?.call(context) ?? _defaultBackground(context),
164+
foregroundBuilder?.call(context) ?? _defaultForeground(context),
165+
) ??
166+
_defaultPresentation(
167+
context,
168+
body,
169+
backgroundBuilder?.call(context) ?? _defaultBackground(context),
170+
foregroundBuilder?.call(context) ?? _defaultForeground(context),
171+
);
172+
173+
// Apply layout
174+
body = _buildLayout(context, body, layoutType);
175+
176+
return ColoredBox(
177+
color: Theme.of(context).colorScheme.surface,
178+
child: body,
179+
);
180+
},
181+
);
182+
}
183+
184+
/// Builds the body based on layout type
185+
Widget _buildBody(BuildContext context, AppLayout layoutType) {
186+
switch (layoutType) {
187+
case AppLayout.MOBILE:
188+
return mobileBodyBuilder?.call(context) ??
189+
narrowBodyBuilder?.call(context) ??
190+
bodyBuilder(context);
191+
case AppLayout.MOBILE_HORIZONTAL:
192+
return horizontalMobileBodyBuilder?.call(context) ??
193+
wideBodyBuilder?.call(context) ??
194+
bodyBuilder(context);
195+
case AppLayout.NARROW:
196+
return narrowBodyBuilder?.call(context) ?? bodyBuilder(context);
197+
case AppLayout.WIDE:
198+
return wideBodyBuilder?.call(context) ?? bodyBuilder(context);
199+
}
200+
}
201+
202+
/// Builds the layout based on layout type
203+
Widget _buildLayout(BuildContext context, Widget body, AppLayout layoutType) {
204+
switch (layoutType) {
205+
case AppLayout.MOBILE:
206+
return mobileLayoutBuilder?.call(context, body) ??
207+
narrowLayoutBuilder?.call(context, body) ??
208+
body;
209+
case AppLayout.MOBILE_HORIZONTAL:
210+
return horizontalMobileLayoutBuilder?.call(context, body) ??
211+
wideLayoutBuilder?.call(context, body) ??
212+
body;
213+
case AppLayout.NARROW:
214+
return narrowLayoutBuilder?.call(context, body) ?? body;
215+
case AppLayout.WIDE:
216+
return wideLayoutBuilder?.call(context, body) ?? body;
217+
}
218+
}
219+
}
220+
221+
/// Default alignment
222+
Widget _defaultAlign(BuildContext context, Widget body, EdgeInsets sideInsets) {
223+
return Padding(
224+
padding: sideInsets + MediaQuery.of(context).padding,
225+
child: body,
226+
);
227+
}
228+
229+
/// Default presentation
230+
Widget _defaultPresentation(
231+
BuildContext context,
232+
Widget body,
233+
Widget background,
234+
Widget foreground,
235+
) {
236+
return Stack(
237+
alignment: AlignmentDirectional.center,
238+
fit: StackFit.expand,
239+
children: [
240+
background,
241+
Padding(
242+
padding: MediaQuery.viewInsetsOf(context),
243+
child: body,
244+
),
245+
foreground,
246+
],
247+
);
248+
}
249+
250+
/// Default background
251+
Widget _defaultBackground(BuildContext context) {
252+
return ColoredBox(
253+
color: Theme.of(context).colorScheme.surface,
254+
child: GestureDetector(
255+
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
256+
child: const SizedBox.expand(),
257+
),
258+
);
259+
}
260+
261+
/// Default foreground
262+
Widget _defaultForeground(BuildContext context) {
263+
return const IgnorePointer(child: SizedBox.expand());
264+
}

lib/src/app_layout.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import 'package:flutter/widgets.dart';
1414

15-
import '_hidden/_hidden.g.dart';
15+
import '_utils/_utils.g.dart';
1616

1717
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1818

@@ -58,8 +58,7 @@ enum AppLayout {
5858
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
5959

6060
ScreenCalculator getCurrentScreenCalculator() {
61-
final firstDisplay =
62-
WidgetsBinding.instance.platformDispatcher.displays.first;
61+
final firstDisplay = WidgetsBinding.instance.platformDispatcher.displays.first;
6362
final displaySize = firstDisplay.size;
6463
final displayPixelRatio = firstDisplay.devicePixelRatio;
6564
final screenSize = displaySize / displayPixelRatio;

lib/src/screen_state.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ abstract base class ScreenState<TScreen extends Screen, TController extends Scre
3434

3535
@override
3636
void initState() {
37-
print('INIT STATE: ${widget.runtimeType}');
3837
this._initController();
3938
super.initState();
4039
}

0 commit comments

Comments
 (0)