Skip to content

Commit 05d0e56

Browse files
committed
enhance dimension ratio
1 parent 02639b5 commit 05d0e56

File tree

5 files changed

+131
-7
lines changed

5 files changed

+131
-7
lines changed

example/dimension_ratio.dart

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_constraintlayout/src/constraint_layout.dart';
3+
4+
import 'custom_app_bar.dart';
5+
6+
class DimensionRatioExample extends StatelessWidget {
7+
const DimensionRatioExample({Key? key}) : super(key: key);
8+
9+
@override
10+
Widget build(BuildContext context) {
11+
return Scaffold(
12+
appBar: const CustomAppBar(
13+
title: 'DimensionRatio',
14+
codePath: 'example/dimension_ratio.dart',
15+
),
16+
body: ConstraintLayout(
17+
children: [
18+
Container(
19+
color: Colors.redAccent,
20+
alignment: Alignment.center,
21+
child: const Text('width: parent width\nheight: 1 / 5 of width'),
22+
).applyConstraint(
23+
width: matchParent,
24+
height: matchConstraint,
25+
widthHeightRatio: 5 / 1,
26+
top: parent.top,
27+
),
28+
Container(
29+
color: Colors.blue,
30+
alignment: Alignment.center,
31+
child: const Text('width: 200\nheight: 200% of width'),
32+
).applyConstraint(
33+
width: 200,
34+
height: matchConstraint,
35+
widthHeightRatio: 1 / 2,
36+
bottomCenterTo: parent,
37+
)
38+
],
39+
),
40+
);
41+
}
42+
}

example/home.dart

+8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
33
import 'badge.dart';
44
import 'barrier.dart';
55
import 'complex_list.dart';
6+
import 'dimension_ratio.dart';
67
import 'guideline.dart';
8+
import 'percentage_layout.dart';
79
import 'summary.dart';
810

911
class ExampleHome extends StatelessWidget {
@@ -40,6 +42,12 @@ class ExampleHome extends StatelessWidget {
4042
button('Badge', () {
4143
push(context, const BadgeExample());
4244
}),
45+
button('PercentageLayout', () {
46+
push(context, const PercentageLayoutExample());
47+
}),
48+
button('DimensionRatio', () {
49+
push(context, const DimensionRatioExample());
50+
}),
4351
const Spacer(),
4452
const Text(
4553
'Powered by Flutter Web & ConstraintLayout',

example/percentage_layout.dart

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_constraintlayout/src/constraint_layout.dart';
3+
4+
import 'custom_app_bar.dart';
5+
6+
class PercentageLayoutExample extends StatelessWidget {
7+
const PercentageLayoutExample({Key? key}) : super(key: key);
8+
9+
@override
10+
Widget build(BuildContext context) {
11+
return Scaffold(
12+
appBar: const CustomAppBar(
13+
title: 'PercentageLayout',
14+
codePath: 'example/percentage_layout.dart',
15+
),
16+
body: ConstraintLayout(
17+
children: [
18+
Container(
19+
color: Colors.redAccent,
20+
alignment: Alignment.center,
21+
child: const Text('width: 50% of parent\nheight: 200'),
22+
).applyConstraint(
23+
width: matchConstraint,
24+
height: 200,
25+
widthPercent: 0.5,
26+
topCenterTo: parent,
27+
),
28+
Container(
29+
color: Colors.blue,
30+
alignment: Alignment.center,
31+
child: const Text('width: 300\nheight: 30% of parent'),
32+
).applyConstraint(
33+
width: 300,
34+
height: matchConstraint,
35+
heightPercent: 0.3,
36+
verticalBias: 1,
37+
centerLeftTo: parent,
38+
)
39+
],
40+
),
41+
);
42+
}
43+
}

lib/src/constraint_layout.dart

+35-6
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ extension ConstrainedWidgetsExt on Widget {
185185
double minHeight = 0,
186186
double maxHeight = matchParent,
187187
double? widthHeightRatio,
188+
bool? ratioBaseOnWidth,
188189
}) {
189190
return Constrained(
190191
key: key,
@@ -231,6 +232,7 @@ extension ConstrainedWidgetsExt on Widget {
231232
minHeight: minHeight,
232233
maxHeight: maxHeight,
233234
widthHeightRatio: widthHeightRatio,
235+
ratioBaseOnWidth: ratioBaseOnWidth,
234236
),
235237
child: this,
236238
);
@@ -526,6 +528,12 @@ class Constraint {
526528
/// inferred (fixed size, matchParent, matchConstraint with two constraints)
527529
final double? widthHeightRatio;
528530

531+
/// By default, ConstraintLayout will automatically decide which side to base on and
532+
/// calculate the size of the other side based on widthHeightRatio. But if both sides
533+
/// are matchConstraint, it cannot be determined automatically. At this point, you need
534+
/// to specify the ratioBaseOnWidth parameter. The default value of null means automatically decide
535+
final bool? ratioBaseOnWidth;
536+
529537
Constraint({
530538
this.id,
531539
this.width = wrapContent,
@@ -569,6 +577,7 @@ class Constraint {
569577
this.minHeight = 0,
570578
this.maxHeight = matchParent,
571579
this.widthHeightRatio,
580+
this.ratioBaseOnWidth,
572581
});
573582

574583
@override
@@ -616,7 +625,8 @@ class Constraint {
616625
maxWidth == other.maxWidth &&
617626
minHeight == other.minHeight &&
618627
maxHeight == other.maxHeight &&
619-
widthHeightRatio == other.widthHeightRatio;
628+
widthHeightRatio == other.widthHeightRatio &&
629+
ratioBaseOnWidth == other.ratioBaseOnWidth;
620630

621631
@override
622632
int get hashCode =>
@@ -660,7 +670,8 @@ class Constraint {
660670
maxWidth.hashCode ^
661671
minHeight.hashCode ^
662672
maxHeight.hashCode ^
663-
widthHeightRatio.hashCode;
673+
widthHeightRatio.hashCode ^
674+
ratioBaseOnWidth.hashCode;
664675

665676
bool checkSize(double size) {
666677
if (size == matchParent || size == wrapContent || size == matchConstraint) {
@@ -1009,6 +1020,11 @@ class Constraint {
10091020
needsLayout = true;
10101021
}
10111022

1023+
if (parentData.ratioBaseOnWidth != ratioBaseOnWidth) {
1024+
parentData.ratioBaseOnWidth = ratioBaseOnWidth;
1025+
needsLayout = true;
1026+
}
1027+
10121028
if (needsLayout) {
10131029
AbstractNode? targetParent = renderObject.parent;
10141030
if (needsRecalculateConstraints) {
@@ -1075,6 +1091,7 @@ class _ConstraintBoxData extends ContainerBoxParentData<RenderBox> {
10751091
double? minHeight;
10761092
double? maxHeight;
10771093
double? widthHeightRatio;
1094+
bool? ratioBaseOnWidth;
10781095

10791096
// for internal use
10801097
late Map<ConstraintId, _ConstrainedNode> _constrainedNodeMap;
@@ -1412,8 +1429,13 @@ class _ConstraintRenderBox extends RenderBox
14121429

14131430
if (element.widthHeightRatio != null) {
14141431
if (element.widthIsExact && element.heightIsExact) {
1415-
throw ConstraintLayoutException(
1416-
'When setting widthHeightRatio for ${element.nodeId}, full constraints cannot be set on both sides at the same time.');
1432+
if (element.width == matchConstraint &&
1433+
element.height == matchConstraint) {
1434+
if (element.ratioBaseOnWidth == null) {
1435+
throw ConstraintLayoutException(
1436+
'When setting widthHeightRatio for ${element.nodeId}, ratioBaseOnWidth is required.');
1437+
}
1438+
}
14171439
} else if (!element.widthIsExact && !element.heightIsExact) {
14181440
throw ConstraintLayoutException(
14191441
'When setting widthHeightRatio for ${element.nodeId}, one side needs full constraints.');
@@ -1715,7 +1737,9 @@ class _ConstraintRenderBox extends RenderBox
17151737
}());
17161738
maxWidth = minWidth;
17171739
} else if (width == matchConstraint) {
1718-
if (element.widthHeightRatio != null && !element.widthIsExact) {
1740+
if (element.widthHeightRatio != null &&
1741+
element.heightIsExact &&
1742+
element.ratioBaseOnWidth != true) {
17191743
/// The width needs to be calculated later based on the height
17201744
element.widthBasedHeight = true;
17211745
minWidth = 0;
@@ -1797,7 +1821,9 @@ class _ConstraintRenderBox extends RenderBox
17971821
}());
17981822
maxHeight = minHeight;
17991823
} else if (height == matchConstraint) {
1800-
if (element.widthHeightRatio != null && element.widthIsExact) {
1824+
if (element.widthHeightRatio != null &&
1825+
element.widthIsExact &&
1826+
element.ratioBaseOnWidth != false) {
18011827
/// The height needs to be calculated later based on the width
18021828
/// minWidth == maxWidth
18031829
minHeight = minWidth / element.widthHeightRatio!;
@@ -2471,6 +2497,8 @@ class _ConstrainedNode {
24712497

24722498
double? get widthHeightRatio => parentData.widthHeightRatio;
24732499

2500+
bool? get ratioBaseOnWidth => parentData.ratioBaseOnWidth;
2501+
24742502
/// fixed size, matchParent, matchConstraint with two constraints
24752503
bool get widthIsExact =>
24762504
width >= 0 ||
@@ -2707,6 +2735,7 @@ class _InternalBox extends RenderBox {
27072735
constraintBoxData.minHeight = 0;
27082736
constraintBoxData.maxHeight = matchParent;
27092737
constraintBoxData.widthHeightRatio = null;
2738+
constraintBoxData.ratioBaseOnWidth = null;
27102739
}
27112740
}
27122741

pubspec.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ flutter:
2626
- example/barrier.dart
2727
- example/complex_list.dart
2828
- example/guideline.dart
29-
- example/summary.dart
29+
- example/summary.dart
30+
- example/percentage_layout.dart
31+
- example/dimension_ratio.dart

0 commit comments

Comments
 (0)