Skip to content

Commit bbfc471

Browse files
committed
add open grammar support
1 parent 6e23eca commit bbfc471

File tree

7 files changed

+243
-10
lines changed

7 files changed

+243
-10
lines changed

README.md

+57
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,63 @@ two-way constraints, such as chains(not yet supported, please use with Flex).
174174
4. showChildDepth
175175
5. debugPrintConstraints
176176
6. showLayoutPerformanceOverlay
177+
24. open grammar gives you more flexibility to organize child elements, solving the problem of using
178+
only limited expressions in the children list
179+
180+
```dart
181+
class OpenGrammarExample extends StatelessWidget {
182+
const OpenGrammarExample({Key? key}) : super(key: key);
183+
184+
@override
185+
Widget build(BuildContext context) {
186+
return Scaffold(
187+
body: ConstraintLayout().open(() {
188+
if (DateTime
189+
.now()
190+
.millisecond % 2 == 0) {
191+
Container(
192+
color: Colors.red,
193+
).applyConstraint(
194+
size: 200,
195+
centerTo: parent,
196+
);
197+
} else {
198+
Container(
199+
color: Colors.yellow,
200+
).applyConstraint(
201+
size: 200,
202+
centerTo: parent,
203+
);
204+
}
205+
206+
for (int i = 0; i < 5; i++) {
207+
Row().open(() {
208+
for (int j = 0; j < 10; j++) {
209+
Text("$i x $j").enter();
210+
const SizedBox(
211+
width: 20,
212+
).enter();
213+
}
214+
}).applyConstraint(
215+
height: 100,
216+
left: parent.left.margin(100),
217+
top: i == 0 ? parent.top : sId(-1).bottom,
218+
);
219+
}
220+
221+
int i = 0;
222+
while (i < 100) {
223+
Text("$i").applyConstraint(
224+
left: parent.left,
225+
top: i == 0 ? parent.top : sId(-1).bottom,
226+
);
227+
i++;
228+
}
229+
}),
230+
);
231+
}
232+
}
233+
```
177234

178235
Follow-up development plan:
179236

README_CN.md

+56
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,62 @@ build 耗时有时甚至超过渲染耗时。
147147
4. showChildDepth
148148
5. debugPrintConstraints
149149
6. showLayoutPerformanceOverlay
150+
24. 开放式语法让你更灵活的来组织子元素,解决了在 children 列表中仅能使用有限的表达式的问题
151+
152+
```dart
153+
class OpenGrammarExample extends StatelessWidget {
154+
const OpenGrammarExample({Key? key}) : super(key: key);
155+
156+
@override
157+
Widget build(BuildContext context) {
158+
return Scaffold(
159+
body: ConstraintLayout().open(() {
160+
if (DateTime
161+
.now()
162+
.millisecond % 2 == 0) {
163+
Container(
164+
color: Colors.red,
165+
).applyConstraint(
166+
size: 200,
167+
centerTo: parent,
168+
);
169+
} else {
170+
Container(
171+
color: Colors.yellow,
172+
).applyConstraint(
173+
size: 200,
174+
centerTo: parent,
175+
);
176+
}
177+
178+
for (int i = 0; i < 5; i++) {
179+
Row().open(() {
180+
for (int j = 0; j < 10; j++) {
181+
Text("$i x $j").enter();
182+
const SizedBox(
183+
width: 20,
184+
).enter();
185+
}
186+
}).applyConstraint(
187+
height: 100,
188+
left: parent.left.margin(100),
189+
top: i == 0 ? parent.top : sId(-1).bottom,
190+
);
191+
}
192+
193+
int i = 0;
194+
while (i < 100) {
195+
Text("$i").applyConstraint(
196+
left: parent.left,
197+
top: i == 0 ? parent.top : sId(-1).bottom,
198+
);
199+
i++;
200+
}
201+
}),
202+
);
203+
}
204+
}
205+
```
150206

151207
后续开发计划:
152208

example/home.dart

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'grid.dart';
1414
import 'guideline.dart';
1515
import 'horizontal_list.dart';
1616
import 'margin.dart';
17+
import 'open_grammar.dart';
1718
import 'percentage_layout.dart';
1819
import 'pinned_position.dart';
1920
import 'relative_id.dart';
@@ -29,6 +30,7 @@ class ExampleHome extends StatelessWidget {
2930

3031
final Map<String, Widget?> exampleMap = {
3132
'Summary': const SummaryExample(),
33+
'Open Grammar': const OpenGrammarExample(),
3234
'Guideline': const GuidelineExample(),
3335
'Barrier': const BarrierExample(),
3436
'Complex List': const ComplexListExample(),

example/open_grammar.dart

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_constraintlayout/flutter_constraintlayout.dart';
3+
4+
import 'custom_app_bar.dart';
5+
6+
class OpenGrammarExample extends StatelessWidget {
7+
const OpenGrammarExample({Key? key}) : super(key: key);
8+
9+
@override
10+
Widget build(BuildContext context) {
11+
return Scaffold(
12+
appBar: const CustomAppBar(
13+
title: 'Open Grammar',
14+
codePath: 'example/open_grammar.dart',
15+
),
16+
body: ConstraintLayout().open(() {
17+
if (DateTime.now().millisecond % 2 == 0) {
18+
Container(
19+
color: Colors.red,
20+
).applyConstraint(
21+
size: 200,
22+
centerTo: parent,
23+
);
24+
} else {
25+
Container(
26+
color: Colors.yellow,
27+
).applyConstraint(
28+
size: 200,
29+
centerTo: parent,
30+
);
31+
}
32+
33+
for (int i = 0; i < 5; i++) {
34+
Row().open(() {
35+
for (int j = 0; j < 10; j++) {
36+
Text("$i x $j").enter();
37+
const SizedBox(
38+
width: 20,
39+
).enter();
40+
}
41+
}).applyConstraint(
42+
height: 100,
43+
left: parent.left.margin(100),
44+
top: i == 0 ? parent.top : sId(-1).bottom,
45+
);
46+
}
47+
48+
int i = 0;
49+
while (i < 100) {
50+
Text("$i").applyConstraint(
51+
left: parent.left,
52+
top: i == 0 ? parent.top : sId(-1).bottom,
53+
);
54+
i++;
55+
}
56+
}),
57+
);
58+
}
59+
}

lib/src/core.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
8383
ConstraintLayout({
8484
Key? key,
8585
this.childConstraints,
86-
required List<Widget> children,
86+
List<Widget>? children,
8787
this.showLayoutPerformanceOverlay = false,
8888
this.showHelperWidgets = false,
8989
this.showClickArea = false,
@@ -96,7 +96,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
9696
this.controller,
9797
}) : super(
9898
key: key,
99-
children: children,
99+
children: children ?? [],
100100
);
101101

102102
@override

lib/src/extensions.dart

+65-7
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,67 @@ class OffBuildWidget extends StatelessWidget {
4848
int get hashCode => id.hashCode;
4949
}
5050

51+
class MultiChildWidgetContext {
52+
static MultiChildWidgetContext? currentContext;
53+
List<Widget> contextChildren = [];
54+
}
55+
56+
extension MultiChildWidgetChildExt on Widget {
57+
Widget enter() {
58+
MultiChildWidgetContext.currentContext?.contextChildren.add(this);
59+
return this;
60+
}
61+
}
62+
63+
extension ConstraintLayoutExt on MultiChildRenderObjectWidget {
64+
Widget open(void Function() block) {
65+
MultiChildWidgetContext? temp = MultiChildWidgetContext.currentContext;
66+
MultiChildWidgetContext context = MultiChildWidgetContext();
67+
MultiChildWidgetContext.currentContext = context;
68+
block();
69+
MultiChildWidgetContext.currentContext = temp;
70+
if (this is ConstraintLayout) {
71+
(this as ConstraintLayout).children.addAll(context.contextChildren);
72+
} else if (this is Row) {
73+
Row row = (this as Row);
74+
return Row(
75+
key: key,
76+
mainAxisAlignment: row.mainAxisAlignment,
77+
mainAxisSize: row.mainAxisSize,
78+
crossAxisAlignment: row.crossAxisAlignment,
79+
textDirection: row.textDirection,
80+
verticalDirection: row.verticalDirection,
81+
textBaseline: row.textBaseline,
82+
children: context.contextChildren);
83+
} else if (this is Column) {
84+
Column column = (this as Column);
85+
return Column(
86+
key: key,
87+
mainAxisAlignment: column.mainAxisAlignment,
88+
mainAxisSize: column.mainAxisSize,
89+
crossAxisAlignment: column.crossAxisAlignment,
90+
textDirection: column.textDirection,
91+
verticalDirection: column.verticalDirection,
92+
textBaseline: column.textBaseline,
93+
children: context.contextChildren);
94+
} else if (this is Stack) {
95+
Stack stack = (this as Stack);
96+
return Stack(
97+
key: key,
98+
alignment: stack.alignment,
99+
textDirection: stack.textDirection,
100+
fit: stack.fit,
101+
overflow: stack.overflow,
102+
clipBehavior: stack.clipBehavior,
103+
children: context.contextChildren);
104+
}
105+
return this;
106+
}
107+
}
108+
51109
/// For easy use
52-
extension ConstrainedWidgetsExt on Widget {
53-
Constrained applyConstraint({
110+
extension ConstrainedWidgetExt on Widget {
111+
Widget applyConstraint({
54112
ConstraintId? id,
55113
double width = wrapContent,
56114
double height = wrapContent,
@@ -188,27 +246,27 @@ extension ConstrainedWidgetsExt on Widget {
188246
calcOffsetCallback: calcOffsetCallback,
189247
),
190248
child: this,
191-
);
249+
).enter();
192250
}
193251

194-
Constrained apply({
252+
Widget apply({
195253
required Constraint constraint,
196254
}) {
197255
return Constrained(
198256
key: key,
199257
constraint: constraint,
200258
child: this,
201-
);
259+
).enter();
202260
}
203261

204-
UnConstrained applyConstraintId({
262+
Widget applyConstraintId({
205263
required ConstraintId id,
206264
}) {
207265
return UnConstrained(
208266
key: key,
209267
id: id,
210268
child: this,
211-
);
269+
).enter();
212270
}
213271

214272
/// When the layout is complex, if the child elements need to be repainted frequently, it

pubspec.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ flutter:
4242
- example/pinned_position.dart
4343
- example/arbitrary_position.dart
4444
- example/constraint_controller.dart
45-
- example/translate.dart
45+
- example/translate.dart
46+
- example/open_grammar.dart

0 commit comments

Comments
 (0)