Skip to content

Commit 3de24c3

Browse files
author
fbchen
committed
add percentage translate
1 parent b70699e commit 3de24c3

File tree

4 files changed

+144
-13
lines changed

4 files changed

+144
-13
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,57 @@ class BarrierExample extends StatelessWidget {
419419

420420
![barrier.gif](https://github.com/hackware1993/flutter-constraintlayout/blob/master/barrier.gif?raw=true)
421421

422+
3. badge
423+
424+
```dart
425+
import 'package:flutter/material.dart';
426+
import 'package:flutter_constraintlayout/constrait_layout/constraint_layout.dart';
427+
428+
class BadgeExample extends StatelessWidget {
429+
const BadgeExample({Key? key}) : super(key: key);
430+
431+
@override
432+
Widget build(BuildContext context) {
433+
ConstraintId anchor = ConstraintId();
434+
return MaterialApp(
435+
home: Scaffold(
436+
body: ConstraintLayout(
437+
children: [
438+
Container(
439+
color: Colors.yellow,
440+
).applyConstraint(
441+
width: 200,
442+
height: 200,
443+
centerTo: parent,
444+
id: anchor,
445+
),
446+
Container(
447+
color: Colors.green,
448+
child: const Text(
449+
'Indeterminate badge size',
450+
style: TextStyle(
451+
color: Colors.black,
452+
fontSize: 20,
453+
),
454+
),
455+
).applyConstraint(
456+
width: wrapContent,
457+
height: wrapContent,
458+
left: anchor.right,
459+
bottom: anchor.top,
460+
translate: const Offset(-0.5, 0.5),
461+
percentageTranslate: true,
462+
)
463+
],
464+
),
465+
),
466+
);
467+
}
468+
}
469+
```
470+
471+
![badge.webp](https://github.com/hackware1993/flutter-constraintlayout/blob/master/badge.webp?raw=true)
472+
422473
# Support me
423474

424475
If it helps you a lot, consider sponsoring me a cup of milk tea.

badge.webp

2.2 KB
Binary file not shown.

lib/constrait_layout/constraint_layout.dart

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ extension WidgetsExt on Widget {
184184
@_wrapperConstraint ConstraintId? centerVerticalTo,
185185
OnLayoutCallback? callback,
186186
double chainWeight = 1,
187+
bool percentageTranslate = false,
187188
}) {
188189
return Constrained(
189190
key: key,
@@ -224,6 +225,7 @@ extension WidgetsExt on Widget {
224225
centerVerticalTo: centerVerticalTo,
225226
callback: callback,
226227
chainWeight: chainWeight,
228+
percentageTranslate: percentageTranslate,
227229
),
228230
child: this,
229231
);
@@ -262,7 +264,14 @@ bool _debugEnsureNotEmptyString(String name, String? value) {
262264

263265
bool _debugEnsurePercent(String name, double? percent) {
264266
if (percent == null || percent < 0 || percent > 1) {
265-
throw ConstraintLayoutException('$name is between [0-1].');
267+
throw ConstraintLayoutException('$name is between [0,1].');
268+
}
269+
return true;
270+
}
271+
272+
bool _debugEnsureNegativePercent(String name, double? percent) {
273+
if (percent == null || percent < -1 || percent > 1) {
274+
throw ConstraintLayoutException('$name is between [-1,1].');
266275
}
267276
return true;
268277
}
@@ -455,6 +464,7 @@ class Constraint {
455464

456465
final OnLayoutCallback? callback;
457466
final double chainWeight;
467+
final bool percentageTranslate;
458468

459469
Constraint({
460470
this.id,
@@ -493,6 +503,7 @@ class Constraint {
493503
@_wrapperConstraint this.centerVerticalTo,
494504
this.callback,
495505
this.chainWeight = 1,
506+
this.percentageTranslate = false,
496507
});
497508

498509
@override
@@ -534,7 +545,8 @@ class Constraint {
534545
bottomRightTo == other.bottomRightTo &&
535546
centerHorizontalTo == other.centerHorizontalTo &&
536547
centerVerticalTo == other.centerVerticalTo &&
537-
callback == other.callback;
548+
callback == other.callback &&
549+
percentageTranslate == other.percentageTranslate;
538550

539551
@override
540552
int get hashCode =>
@@ -572,7 +584,8 @@ class Constraint {
572584
bottomRightTo.hashCode ^
573585
centerHorizontalTo.hashCode ^
574586
centerVerticalTo.hashCode ^
575-
callback.hashCode;
587+
callback.hashCode ^
588+
percentageTranslate.hashCode;
576589

577590
bool checkSize(double size) {
578591
if (size == matchParent || size == wrapContent || size == matchConstraint) {
@@ -605,20 +618,26 @@ class Constraint {
605618
assert(_debugEnsurePercent('heightPercent', heightPercent));
606619
assert(_debugEnsurePercent('horizontalBias', horizontalBias));
607620
assert(_debugEnsurePercent('verticalBias', verticalBias));
608-
assert(!percentageMargin || _debugEnsurePercent('leftMargin', margin.left));
609-
assert(!percentageMargin || _debugEnsurePercent('topMargin', margin.top));
610-
assert(
611-
!percentageMargin || _debugEnsurePercent('rightMargin', margin.right));
612621
assert(!percentageMargin ||
613-
_debugEnsurePercent('bottomMargin', margin.bottom));
622+
_debugEnsureNegativePercent('leftMargin', margin.left));
623+
assert(!percentageMargin ||
624+
_debugEnsureNegativePercent('topMargin', margin.top));
625+
assert(!percentageMargin ||
626+
_debugEnsureNegativePercent('rightMargin', margin.right));
627+
assert(!percentageMargin ||
628+
_debugEnsureNegativePercent('bottomMargin', margin.bottom));
614629
assert(!percentageMargin ||
615-
_debugEnsurePercent('leftGoneMargin', goneMargin.left));
630+
_debugEnsureNegativePercent('leftGoneMargin', goneMargin.left));
616631
assert(!percentageMargin ||
617-
_debugEnsurePercent('topGoneMargin', goneMargin.top));
632+
_debugEnsureNegativePercent('topGoneMargin', goneMargin.top));
618633
assert(!percentageMargin ||
619-
_debugEnsurePercent('rightGoneMargin', goneMargin.right));
634+
_debugEnsureNegativePercent('rightGoneMargin', goneMargin.right));
620635
assert(!percentageMargin ||
621-
_debugEnsurePercent('bottomGoneMargin', goneMargin.bottom));
636+
_debugEnsureNegativePercent('bottomGoneMargin', goneMargin.bottom));
637+
assert(!percentageTranslate ||
638+
_debugEnsureNegativePercent('xTranslate', translate.dx));
639+
assert(!percentageTranslate ||
640+
_debugEnsureNegativePercent('yTranslate', translate.dy));
622641
return true;
623642
}
624643

@@ -849,6 +868,11 @@ class Constraint {
849868

850869
parentData.callback = callback;
851870

871+
if (parentData.percentageTranslate != percentageTranslate) {
872+
parentData.percentageTranslate = percentageTranslate;
873+
needsPaint = true;
874+
}
875+
852876
if (needsLayout) {
853877
AbstractNode? targetParent = renderObject.parent;
854878
if (targetParent is RenderObject) {
@@ -904,6 +928,7 @@ class _ConstraintBoxData extends ContainerBoxParentData<RenderBox> {
904928
double? horizontalBias;
905929
double? verticalBias;
906930
OnLayoutCallback? callback;
931+
bool? percentageTranslate;
907932

908933
// for internal use
909934
late Map<ConstraintId, _ConstrainedNode> _tempConstrainedNodes;
@@ -2028,7 +2053,15 @@ class _ConstrainedNode {
20282053
}
20292054
}
20302055

2031-
Offset get translate => parentData.translate!;
2056+
Offset get translate {
2057+
if (!percentageTranslate) {
2058+
return parentData.translate!;
2059+
} else {
2060+
double dx = renderBox!.size.width * parentData.translate!.dx;
2061+
double dy = renderBox!.size.height * parentData.translate!.dy;
2062+
return Offset(dx, dy);
2063+
}
2064+
}
20322065

20332066
bool get translateConstraint => parentData.translateConstraint!;
20342067

@@ -2064,6 +2097,8 @@ class _ConstrainedNode {
20642097

20652098
BarrierDirection? get direction => parentData._direction;
20662099

2100+
bool get percentageTranslate => parentData.percentageTranslate!;
2101+
20672102
set offset(Offset value) {
20682103
parentData.offset = value;
20692104
}
@@ -2286,6 +2321,7 @@ class _InternalBox extends RenderBox {
22862321
constraintBoxData.callback = null;
22872322
constraintBoxData._direction = null;
22882323
constraintBoxData._referencedIds = null;
2324+
constraintBoxData.percentageTranslate = false;
22892325
}
22902326
}
22912327

lib/examples/badge.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_constraintlayout/constrait_layout/constraint_layout.dart';
3+
4+
class BadgeExample extends StatelessWidget {
5+
const BadgeExample({Key? key}) : super(key: key);
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
ConstraintId anchor = ConstraintId();
10+
return MaterialApp(
11+
home: Scaffold(
12+
body: ConstraintLayout(
13+
children: [
14+
Container(
15+
color: Colors.yellow,
16+
).applyConstraint(
17+
width: 200,
18+
height: 200,
19+
centerTo: parent,
20+
id: anchor,
21+
),
22+
Container(
23+
color: Colors.green,
24+
child: const Text(
25+
'Indeterminate badge size',
26+
style: TextStyle(
27+
color: Colors.black,
28+
fontSize: 20,
29+
),
30+
),
31+
).applyConstraint(
32+
width: wrapContent,
33+
height: wrapContent,
34+
left: anchor.right,
35+
bottom: anchor.top,
36+
translate: const Offset(-0.5, 0.5),
37+
percentageTranslate: true,
38+
)
39+
],
40+
),
41+
),
42+
);
43+
}
44+
}

0 commit comments

Comments
 (0)