Skip to content

Commit 77d9bf6

Browse files
author
Francesco Iapicca
committed
[adaptive_style] implemented AdaptiveStack
1 parent b46a866 commit 77d9bf6

18 files changed

+450
-276
lines changed

examples/adaptive_style_example/lib/main.dart

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ class MyApplication extends StatelessWidget {
77
const MyApplication({super.key});
88

99
@override
10-
Widget build(context) => const SizeRefProvider(
11-
deviceSizes: [DeviceSize.iphoneSE],
12-
child: MaterialApp(
10+
Widget build(context) => ScaleRefProvider(
11+
deviceSizes: const [DeviceSize.iphoneSE],
12+
builder: (context) => const MaterialApp(
1313
home: MyHomePage(),
1414
),
1515
);
@@ -19,21 +19,27 @@ class MyHomePage extends StatelessWidget {
1919
const MyHomePage({super.key});
2020

2121
@override
22-
Widget build(context) => SizeRefBuilder(builder: (context, sizeRef) {
23-
return switch (sizeRef.size) {
24-
(DeviceSize.iphoneSE) => Scaffold(
25-
backgroundColor: Colors.black,
26-
body: Center(
27-
child: FlutterLogo(
28-
size: 100 * sizeRef.scale.min,
29-
),
22+
Widget build(context) => Material(
23+
child: AdaptiveStackBuilder(
24+
builder: (context, scaleRef, parentSize) => [
25+
AdaptiveEdgePositioned(
26+
parentSize: parentSize,
27+
padding: const EdgeInsets.all(10),
28+
dimension: 100,
29+
edge: Edge.bottom,
30+
builder: (context, scaleRef, parentSize) => const ColoredBox(
31+
color: Colors.red,
3032
),
3133
),
32-
_ => const Scaffold(
33-
body: Center(
34-
child: FlutterLogo(size: 100),
35-
),
36-
),
37-
};
38-
});
34+
],
35+
),
36+
// child: AdaptiveEdgePositioned(
37+
// padding: const EdgeInsets.all(10),
38+
// dimension: 100,
39+
// edge: Edge.bottom,
40+
// builder: (context, scaleRef, _) => const ColoredBox(
41+
// color: Colors.red,
42+
// ),
43+
// ),
44+
);
3945
}
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
library adaptive_style;
22

3-
export 'src/adaptive_size_builder.dart';
4-
export 'src/adaptive_size_provider.dart';
3+
export 'src/adaptive_edge_positioned.dart';
4+
export 'src/adaptive_mediaquery_widget.dart';
5+
export 'src/adaptive_stack.dart';
6+
export 'src/adaptive_widget_builder.dart';
7+
export 'src/adaptive_widget.dart';
58
export 'src/device_size.dart';
69
export 'src/extension.dart';
7-
export 'src/inherited_adaptive_size.dart';
10+
export 'src/inherited_scale_ref.dart';
11+
export 'src/scale_ref_provider.dart';
12+
export 'src/scale_ref.dart';
13+
export 'src/size_scale.dart';
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import 'adaptive_widget.dart';
4+
import 'adaptive_widget_builder.dart';
5+
6+
enum Edge { top, bottom, left, right }
7+
8+
class AdaptiveEdgePositioned extends AdaptiveWidget {
9+
final EdgeInsets padding;
10+
final double dimension;
11+
final AdaptiveWidgetBuilder _builder;
12+
final Edge edge;
13+
const AdaptiveEdgePositioned({
14+
super.key,
15+
this.padding = EdgeInsets.zero,
16+
required AdaptiveWidgetBuilder builder,
17+
required this.dimension,
18+
required this.edge,
19+
required this.parentSize,
20+
}) : _builder = builder;
21+
22+
@override
23+
Widget builder(context, scaleRef, parentSize) =>
24+
25+
/// TODO should calculate parent data
26+
ScalableEdgePositioned(
27+
edge: edge,
28+
dimension: dimension,
29+
scale: scaleRef.scale.min,
30+
child: _builder(context, scaleRef, parentSize),
31+
);
32+
33+
@override
34+
final Size parentSize;
35+
}
36+
37+
class ScalableEdgePositioned extends Positioned {
38+
final EdgeInsets padding;
39+
final double dimension;
40+
final double scale;
41+
final Edge edge;
42+
const ScalableEdgePositioned({
43+
required this.edge,
44+
required super.child,
45+
required this.dimension,
46+
this.padding = EdgeInsets.zero,
47+
required this.scale,
48+
super.key,
49+
});
50+
51+
@override
52+
@protected
53+
@visibleForTesting
54+
double? get left {
55+
return switch (edge) {
56+
(Edge.right) => null,
57+
_ => padding.left * scale,
58+
};
59+
}
60+
61+
@override
62+
@protected
63+
@visibleForTesting
64+
double? get right {
65+
return switch (edge) {
66+
(Edge.left) => null,
67+
_ => padding.right * scale,
68+
};
69+
}
70+
71+
@override
72+
@protected
73+
@visibleForTesting
74+
double? get bottom {
75+
return switch (edge) {
76+
(Edge.top) => null,
77+
_ => padding.bottom * scale,
78+
};
79+
}
80+
81+
@override
82+
@protected
83+
@visibleForTesting
84+
double? get top {
85+
return switch (edge) {
86+
(Edge.bottom) => null,
87+
_ => padding.top * scale,
88+
};
89+
}
90+
91+
@override
92+
double? get height {
93+
return switch (edge) {
94+
(Edge.bottom || Edge.top) => (dimension - padding.vertical) * scale,
95+
_ => null,
96+
};
97+
}
98+
99+
@override
100+
double? get width {
101+
return switch (edge) {
102+
(Edge.left || Edge.right) => (dimension - padding.horizontal) * scale,
103+
_ => null,
104+
};
105+
}
106+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:yak_flutter/yak_flutter.dart';
3+
4+
class AdaptiveMediaQueryWidget extends MediaQueryWidget {
5+
final double scale;
6+
final WidgetBuilder builder;
7+
const AdaptiveMediaQueryWidget({
8+
required this.builder,
9+
required this.scale,
10+
super.key,
11+
});
12+
13+
@override
14+
Widget build(context) => key == null
15+
? Builder(builder: builder)
16+
: KeyedSubtree(
17+
key: key,
18+
child: Builder(builder: builder),
19+
);
20+
21+
@override
22+
MediaQueryData mediaQueryFrom(MediaQueryData mediaQuery) =>
23+
mediaQuery.copyWith(
24+
textScaler: TextScaler.linear(scale),
25+
);
26+
}

packages/adaptive_style/lib/src/adaptive_size_builder.dart

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:meta/meta.dart';
3+
4+
import 'adaptive_widget.dart';
5+
import 'adaptive_widget_builder.dart';
6+
import 'scale_ref.dart';
7+
8+
class AdaptiveStack extends AdaptiveWidget {
9+
final AlignmentDirectional alignment;
10+
final AdaptiveChildrenBuilder _builder;
11+
final Clip clipBehavior;
12+
final StackFit fit;
13+
final TextDirection? textDirection;
14+
15+
const AdaptiveStack({
16+
required AdaptiveChildrenBuilder builder,
17+
required this.parentSize,
18+
this.alignment = AlignmentDirectional.topStart,
19+
this.clipBehavior = Clip.hardEdge,
20+
this.fit = StackFit.loose,
21+
this.textDirection,
22+
super.key,
23+
}) : _builder = builder;
24+
25+
@override
26+
Widget builder(context, scaleRef, parentSize) => SizedBox.fromSize(
27+
size: parentSize,
28+
child: AdaptiveStackLayout(
29+
parentSize: parentSize,
30+
scaleRef: scaleRef,
31+
context: context,
32+
builder: _builder,
33+
alignment: alignment,
34+
textDirection: textDirection,
35+
fit: fit,
36+
clipBehavior: clipBehavior,
37+
),
38+
);
39+
40+
@override
41+
final Size parentSize;
42+
}
43+
44+
class AdaptiveStackLayout extends Stack {
45+
final AdaptiveChildrenBuilder builder;
46+
final Size parentSize;
47+
final ScaleRef scaleRef;
48+
final BuildContext context;
49+
const AdaptiveStackLayout({
50+
super.key,
51+
super.alignment = AlignmentDirectional.topStart,
52+
super.textDirection,
53+
super.fit = StackFit.loose,
54+
super.clipBehavior = Clip.hardEdge,
55+
required this.builder,
56+
required this.parentSize,
57+
required this.context,
58+
required this.scaleRef,
59+
});
60+
61+
@override
62+
@nonVirtual
63+
List<Widget> get children => builder(context, scaleRef, parentSize);
64+
}
65+
66+
class AdaptiveStackBuilder extends LayoutBuilder {
67+
final AlignmentDirectional alignment;
68+
final Clip clipBehavior;
69+
final StackFit fit;
70+
final TextDirection? textDirection;
71+
AdaptiveStackBuilder({
72+
required AdaptiveChildrenBuilder builder,
73+
this.alignment = AlignmentDirectional.topStart,
74+
this.clipBehavior = Clip.hardEdge,
75+
this.fit = StackFit.loose,
76+
this.textDirection,
77+
super.key,
78+
}) : super(
79+
builder: (context, contraints) => AdaptiveStack(
80+
alignment: alignment,
81+
builder: builder,
82+
clipBehavior: clipBehavior,
83+
fit: fit,
84+
parentSize: contraints.biggest,
85+
textDirection: textDirection,
86+
));
87+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter/widgets.dart';
3+
4+
import 'inherited_scale_ref.dart';
5+
import 'scale_ref.dart';
6+
7+
abstract class AdaptiveWidget extends Widget implements StatelessWidget {
8+
const AdaptiveWidget({super.key});
9+
10+
@override
11+
StatelessElement createElement() => StatelessElement(this);
12+
13+
@override
14+
@protected
15+
@nonVirtual
16+
Widget build(BuildContext context) {
17+
final maybeScaleRef = InheritedScaleRef.maybeOf(context);
18+
if (maybeScaleRef == null) {
19+
throw Exception('ScaleRef not found in context,'
20+
' make sure to have "ScaleRefProvider" in your Widget Tree');
21+
}
22+
return builder(context, maybeScaleRef, parentSize);
23+
}
24+
25+
Size get parentSize;
26+
27+
Widget builder(BuildContext context, ScaleRef scaleRef, Size parentSize);
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import 'scale_ref.dart';
4+
5+
/// a function that return a `Widget` from a
6+
/// `BuildContext` a `ScaleRef` and the `Size` of the parent Widget
7+
typedef AdaptiveWidgetBuilder = Widget Function(
8+
BuildContext context,
9+
ScaleRef scaleRef,
10+
Size parentSize,
11+
);
12+
13+
mixin AdaptiveWidgetBuilderMixin on Widget {
14+
Widget builder(
15+
BuildContext context,
16+
ScaleRef scaleRef,
17+
Size parentSize,
18+
);
19+
}
20+
21+
typedef AdaptiveChildrenBuilder = List<Widget> Function(
22+
BuildContext context,
23+
ScaleRef scaleRef,
24+
Size parentSize,
25+
);
26+
27+
mixin AdaptiveChildrenBuilderrMixin on Widget {
28+
List<Widget> builder(
29+
BuildContext context,
30+
ScaleRef scaleRef,
31+
Size parentSize,
32+
);
33+
}

0 commit comments

Comments
 (0)