Unverified Commit 75ca31b0 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Correct Badge interpretation of its alignment parameter (#119853)

parent d8154fde
...@@ -16,7 +16,7 @@ class _${blockName}DefaultsM3 extends BadgeThemeData { ...@@ -16,7 +16,7 @@ class _${blockName}DefaultsM3 extends BadgeThemeData {
smallSize: ${tokens["md.comp.badge.size"]}, smallSize: ${tokens["md.comp.badge.size"]},
largeSize: ${tokens["md.comp.badge.large.size"]}, largeSize: ${tokens["md.comp.badge.large.size"]},
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
alignment: const AlignmentDirectional(12, -4), alignment: AlignmentDirectional.topEnd,
); );
final BuildContext context; final BuildContext context;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'badge_theme.dart'; import 'badge_theme.dart';
...@@ -35,6 +36,7 @@ class Badge extends StatelessWidget { ...@@ -35,6 +36,7 @@ class Badge extends StatelessWidget {
this.textStyle, this.textStyle,
this.padding, this.padding,
this.alignment, this.alignment,
this.offset,
this.label, this.label,
this.isLabelVisible = true, this.isLabelVisible = true,
this.child, this.child,
...@@ -54,6 +56,7 @@ class Badge extends StatelessWidget { ...@@ -54,6 +56,7 @@ class Badge extends StatelessWidget {
this.textStyle, this.textStyle,
this.padding, this.padding,
this.alignment, this.alignment,
this.offset,
required int count, required int count,
this.isLabelVisible = true, this.isLabelVisible = true,
this.child, this.child,
...@@ -106,13 +109,29 @@ class Badge extends StatelessWidget { ...@@ -106,13 +109,29 @@ class Badge extends StatelessWidget {
/// left and right if the theme's value is null. /// left and right if the theme's value is null.
final EdgeInsetsGeometry? padding; final EdgeInsetsGeometry? padding;
/// The location of the [label] relative to the [child]. /// Combined with [offset] to determine the location of the [label]
/// relative to the [child].
///
/// The alignment positions the label in the same way a child of an
/// [Align] widget is positioned, except that, the alignment is
/// resolved as if the label was a [largeSize] square and [offset]
/// is added to the result.
///
/// This value is only used if [label] is non-null.
///
/// Defaults to the [BadgeTheme]'s alignment, or
/// [AlignmentDirectional.topEnd] if the theme's value is null.
final AlignmentGeometry? alignment;
/// Combined with [alignment] to determine the location of the [label]
/// relative to the [child].
/// ///
/// This value is only used if [label] is non-null. /// This value is only used if [label] is non-null.
/// ///
/// Defaults to the [BadgeTheme]'s alignment, or `start = 12` /// Defaults to the [BadgeTheme]'s offset, or
/// and `top = -4` if the theme's value is null. /// if the theme's value is null then `Offset(4, -4)` for
final AlignmentDirectional? alignment; /// [TextDirection.ltr] or `Offset(-4, -4)` for [TextDirection.rtl].
final Offset? offset;
/// The badge's content, typically a [Text] widget that contains 1 to 4 /// The badge's content, typically a [Text] widget that contains 1 to 4
/// characters. /// characters.
...@@ -168,24 +187,99 @@ class Badge extends StatelessWidget { ...@@ -168,24 +187,99 @@ class Badge extends StatelessWidget {
return badge; return badge;
} }
final AlignmentDirectional effectiveAlignment = alignment ?? badgeTheme.alignment ?? defaults.alignment!; final AlignmentGeometry effectiveAlignment = alignment ?? badgeTheme.alignment ?? defaults.alignment!;
final TextDirection textDirection = Directionality.of(context);
final Offset defaultOffset = textDirection == TextDirection.ltr ? const Offset(4, -4) : const Offset(-4, -4);
final Offset effectiveOffset = offset ?? badgeTheme.offset ?? defaultOffset;
return return
Stack( Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: <Widget>[ children: <Widget>[
child!, child!,
Positioned.directional( Positioned.fill(
textDirection: Directionality.of(context), child: _Badge(
start: label == null ? null : effectiveAlignment.start, alignment: effectiveAlignment,
end: label == null ? 0 : null, offset: label == null ? Offset.zero : effectiveOffset,
top: label == null ? 0 : effectiveAlignment.y, textDirection: textDirection,
child: badge, child: badge,
), ),
),
], ],
); );
} }
} }
class _Badge extends SingleChildRenderObjectWidget {
const _Badge({
required this.alignment,
required this.offset,
required this.textDirection,
super.child, // the badge
});
final AlignmentGeometry alignment;
final Offset offset;
final TextDirection textDirection;
@override
_RenderBadge createRenderObject(BuildContext context) {
return _RenderBadge(
alignment: alignment,
offset: offset,
textDirection: Directionality.maybeOf(context),
);
}
@override
void updateRenderObject(BuildContext context, _RenderBadge renderObject) {
renderObject
..alignment = alignment
..offset = offset
..textDirection = Directionality.maybeOf(context);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment));
properties.add(DiagnosticsProperty<Offset>('offset', offset));
}
}
class _RenderBadge extends RenderAligningShiftedBox {
_RenderBadge({
super.textDirection,
super.alignment,
required Offset offset,
}) : _offset = offset;
Offset get offset => _offset;
Offset _offset;
set offset(Offset value) {
if (_offset == value) {
return;
}
_offset = value;
markNeedsLayout();
}
@override
void performLayout() {
final BoxConstraints constraints = this.constraints;
assert(constraints.hasBoundedWidth);
assert(constraints.hasBoundedHeight);
size = constraints.biggest;
child!.layout(const BoxConstraints(), parentUsesSize: true);
final double badgeSize = child!.size.height;
final Alignment resolvedAlignment = alignment.resolve(textDirection);
final BoxParentData childParentData = child!.parentData! as BoxParentData;
childParentData.offset = offset + resolvedAlignment.alongOffset(Offset(size.width - badgeSize, size.height - badgeSize));
}
}
// BEGIN GENERATED TOKEN PROPERTIES - Badge // BEGIN GENERATED TOKEN PROPERTIES - Badge
// Do not edit by hand. The code between the "BEGIN GENERATED" and // Do not edit by hand. The code between the "BEGIN GENERATED" and
...@@ -200,7 +294,7 @@ class _BadgeDefaultsM3 extends BadgeThemeData { ...@@ -200,7 +294,7 @@ class _BadgeDefaultsM3 extends BadgeThemeData {
smallSize: 6.0, smallSize: 6.0,
largeSize: 16.0, largeSize: 16.0,
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
alignment: const AlignmentDirectional(12, -4), alignment: AlignmentDirectional.topEnd,
); );
final BuildContext context; final BuildContext context;
......
...@@ -41,6 +41,7 @@ class BadgeThemeData with Diagnosticable { ...@@ -41,6 +41,7 @@ class BadgeThemeData with Diagnosticable {
this.textStyle, this.textStyle,
this.padding, this.padding,
this.alignment, this.alignment,
this.offset,
}); });
/// Overrides the default value for [Badge.backgroundColor]. /// Overrides the default value for [Badge.backgroundColor].
...@@ -62,7 +63,10 @@ class BadgeThemeData with Diagnosticable { ...@@ -62,7 +63,10 @@ class BadgeThemeData with Diagnosticable {
final EdgeInsetsGeometry? padding; final EdgeInsetsGeometry? padding;
/// Overrides the default value for [Badge.alignment]. /// Overrides the default value for [Badge.alignment].
final AlignmentDirectional? alignment; final AlignmentGeometry? alignment;
/// Overrides the default value for [Badge.offset].
final Offset? offset;
/// Creates a copy of this object but with the given fields replaced with the /// Creates a copy of this object but with the given fields replaced with the
/// new values. /// new values.
...@@ -73,7 +77,8 @@ class BadgeThemeData with Diagnosticable { ...@@ -73,7 +77,8 @@ class BadgeThemeData with Diagnosticable {
double? largeSize, double? largeSize,
TextStyle? textStyle, TextStyle? textStyle,
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
AlignmentDirectional? alignment, AlignmentGeometry? alignment,
Offset? offset,
}) { }) {
return BadgeThemeData( return BadgeThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
...@@ -83,6 +88,7 @@ class BadgeThemeData with Diagnosticable { ...@@ -83,6 +88,7 @@ class BadgeThemeData with Diagnosticable {
textStyle: textStyle ?? this.textStyle, textStyle: textStyle ?? this.textStyle,
padding: padding ?? this.padding, padding: padding ?? this.padding,
alignment: alignment ?? this.alignment, alignment: alignment ?? this.alignment,
offset: offset ?? this.offset,
); );
} }
...@@ -95,7 +101,8 @@ class BadgeThemeData with Diagnosticable { ...@@ -95,7 +101,8 @@ class BadgeThemeData with Diagnosticable {
largeSize: lerpDouble(a?.largeSize, b?.largeSize, t), largeSize: lerpDouble(a?.largeSize, b?.largeSize, t),
textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t), textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t),
padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t), padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t),
alignment: AlignmentDirectional.lerp(a?.alignment, b?.alignment, t), alignment: AlignmentGeometry.lerp(a?.alignment, b?.alignment, t),
offset: Offset.lerp(a?.offset, b?.offset, t),
); );
} }
...@@ -108,6 +115,7 @@ class BadgeThemeData with Diagnosticable { ...@@ -108,6 +115,7 @@ class BadgeThemeData with Diagnosticable {
textStyle, textStyle,
padding, padding,
alignment, alignment,
offset,
); );
@override @override
...@@ -125,7 +133,8 @@ class BadgeThemeData with Diagnosticable { ...@@ -125,7 +133,8 @@ class BadgeThemeData with Diagnosticable {
&& other.largeSize == largeSize && other.largeSize == largeSize
&& other.textStyle == textStyle && other.textStyle == textStyle
&& other.padding == padding && other.padding == padding
&& other.alignment == alignment; && other.alignment == alignment
&& other.offset == offset;
} }
@override @override
...@@ -137,7 +146,8 @@ class BadgeThemeData with Diagnosticable { ...@@ -137,7 +146,8 @@ class BadgeThemeData with Diagnosticable {
properties.add(DoubleProperty('largeSize', largeSize, defaultValue: null)); properties.add(DoubleProperty('largeSize', largeSize, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: null)); properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: null));
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null)); properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
properties.add(DiagnosticsProperty<AlignmentDirectional>('alignment', alignment, defaultValue: null)); properties.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment, defaultValue: null));
properties.add(DiagnosticsProperty<Offset>('offset', offset, defaultValue: null));
} }
} }
......
...@@ -37,7 +37,8 @@ void main() { ...@@ -37,7 +37,8 @@ void main() {
theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onError), theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onError),
); );
// default badge alignment = AlignmentDirectional(12, -4) // default badge alignment = AlignmentDirection.topEnd
// default offset for LTR = Offset(4, -4)
// default padding = EdgeInsets.symmetric(horizontal: 4) // default padding = EdgeInsets.symmetric(horizontal: 4)
// default largeSize = 16 // default largeSize = 16
// '0'.width = 12 // '0'.width = 12
...@@ -46,16 +47,9 @@ void main() { ...@@ -46,16 +47,9 @@ void main() {
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
expect(tester.getTopLeft(find.byType(Badge)), Offset.zero); expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
// x = alignment.start + padding.left
// y = alignment.top
expect(tester.getTopLeft(find.text('0')), const Offset(16, -4)); expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
final RenderBox box = tester.renderObject(find.byType(Badge)); final RenderBox box = tester.renderObject(find.byType(Badge));
// '0'.width = 12
// L = alignment.start
// T = alignment.top
// R = L + '0'.width + padding.width
// B = T + largeSize, R = largeSize/2
expect(box, paints..rrect(rrect: RRect.fromLTRBR(12, -4, 32, 12, const Radius.circular(8)), color: theme.colorScheme.error)); expect(box, paints..rrect(rrect: RRect.fromLTRBR(12, -4, 32, 12, const Radius.circular(8)), color: theme.colorScheme.error));
}); });
...@@ -89,26 +83,13 @@ void main() { ...@@ -89,26 +83,13 @@ void main() {
theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onError), theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onError),
); );
// default badge alignment = AlignmentDirectional(12, -4)
// default padding = EdgeInsets.symmetric(horizontal: 4)
// default largeSize = 16
// '0'.width = 12
// icon.width = 24
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
expect(tester.getTopLeft(find.byType(Badge)), Offset.zero); expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
// x = icon.width - alignment.start - '0'.width - padding.right expect(tester.getTopLeft(find.text('0')), const Offset(0, -4));
// y = alignment.top
expect(tester.getTopLeft(find.text('0')), const Offset(-4, -4));
final RenderBox box = tester.renderObject(find.byType(Badge)); final RenderBox box = tester.renderObject(find.byType(Badge));
// L = icon.width - alignment.start - '0.width' - padding.width expect(box, paints..rrect(rrect: RRect.fromLTRBR(-4, -4, 16, 12, const Radius.circular(8)), color: theme.colorScheme.error));
// T = alignment.top
// R = L + '0.width' + padding.width
// B = T + largeSize
// R = largeSize/2
expect(box, paints..rrect(rrect: RRect.fromLTRBR(-8, -4, 12, 12, const Radius.circular(8)), color: theme.colorScheme.error));
}); });
// Essentially the same as 'Large Badge defaults' // Essentially the same as 'Large Badge defaults'
...@@ -282,4 +263,153 @@ void main() { ...@@ -282,4 +263,153 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(Badge)); final RenderBox box = tester.renderObject(find.byType(Badge));
expect(box, isNot(paints..rrect())); expect(box, isNot(paints..rrect()));
}); });
testWidgets('Large Badge alignment', (WidgetTester tester) async {
const Radius badgeRadius = Radius.circular(8);
Widget buildFrame(Alignment alignment, [Offset offset = Offset.zero]) {
return MaterialApp(
theme: ThemeData.light(useMaterial3: true),
home: Align(
alignment: Alignment.topLeft,
child: Badge(
// Default largeSize = 16, badge with label is "large".
label: Container(width: 8, height: 8, color: Colors.blue),
alignment: alignment,
offset: offset,
child: Container(
color: const Color(0xFF00FF00),
width: 200,
height: 200,
),
),
),
);
}
await tester.pumpWidget(buildFrame(Alignment.topLeft));
final RenderBox box = tester.renderObject(find.byType(Badge));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 0, 16, 16, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topCenter));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 8, 0, 100 + 8, 16, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 0, 200, 16, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerLeft));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 100 - 8, 16, 100 + 8, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 100 - 8, 200, 100 + 8, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomLeft));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 200 - 16, 16, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomCenter));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 8, 200 - 16, 100 + 8, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 200 - 16, 200, 200, badgeRadius)));
const Offset offset = Offset(5, 10);
await tester.pumpWidget(buildFrame(Alignment.topLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 0, 16, 16, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.topCenter, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 8, 0, 100 + 8, 16, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.topRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 0, 200, 16, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.centerLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 100 - 8, 16, 100 + 8, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.centerRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 100 - 8, 200, 100 + 8, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.bottomLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 200 - 16, 16, 200, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.bottomCenter, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 8, 200 - 16, 100 + 8, 200, badgeRadius).shift(offset)));
await tester.pumpWidget(buildFrame(Alignment.bottomRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 16, 200 - 16, 200, 200, badgeRadius).shift(offset)));
});
testWidgets('Small Badge alignment', (WidgetTester tester) async {
const Radius badgeRadius = Radius.circular(3);
Widget buildFrame(Alignment alignment, [Offset offset = Offset.zero]) {
return MaterialApp(
theme: ThemeData.light(useMaterial3: true),
home: Align(
alignment: Alignment.topLeft,
child: Badge(
// Default smallSize = 6, badge without label is "small".
alignment: alignment,
offset: offset, // Not used for smallSize badges.
child: Container(
color: const Color(0xFF00FF00),
width: 200,
height: 200,
),
),
),
);
}
await tester.pumpWidget(buildFrame(Alignment.topLeft));
final RenderBox box = tester.renderObject(find.byType(Badge));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 0, 6, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topCenter));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 3, 0, 100 + 3, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 0, 200, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerLeft));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 100 - 3, 6, 100 + 3, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 100 - 3, 200, 100 + 3, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomLeft));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 200 - 6, 6, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomCenter));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 3, 200 - 6, 100 + 3, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomRight));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 200 - 6, 200, 200, badgeRadius)));
const Offset offset = Offset(5, 10); // Not used for smallSize Badges.
await tester.pumpWidget(buildFrame(Alignment.topLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 0, 6, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topCenter, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 3, 0, 100 + 3, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.topRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 0, 200, 6, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 100 - 3, 6, 100 + 3, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.centerRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 100 - 3, 200, 100 + 3, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomLeft, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(0, 200 - 6, 6, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomCenter, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(100 - 3, 200 - 6, 100 + 3, 200, badgeRadius)));
await tester.pumpWidget(buildFrame(Alignment.bottomRight, offset));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(200 - 6, 200 - 6, 200, 200, badgeRadius)));
});
} }
...@@ -23,6 +23,7 @@ void main() { ...@@ -23,6 +23,7 @@ void main() {
expect(themeData.textStyle, null); expect(themeData.textStyle, null);
expect(themeData.padding, null); expect(themeData.padding, null);
expect(themeData.alignment, null); expect(themeData.alignment, null);
expect(themeData.offset, null);
}); });
testWidgets('Default BadgeThemeData debugFillProperties', (WidgetTester tester) async { testWidgets('Default BadgeThemeData debugFillProperties', (WidgetTester tester) async {
...@@ -47,6 +48,7 @@ void main() { ...@@ -47,6 +48,7 @@ void main() {
textStyle: TextStyle(fontSize: 4), textStyle: TextStyle(fontSize: 4),
padding: EdgeInsets.all(5), padding: EdgeInsets.all(5),
alignment: AlignmentDirectional(6, 7), alignment: AlignmentDirectional(6, 7),
offset: Offset.zero,
).debugFillProperties(builder); ).debugFillProperties(builder);
final List<String> description = builder.properties final List<String> description = builder.properties
...@@ -61,7 +63,8 @@ void main() { ...@@ -61,7 +63,8 @@ void main() {
'largeSize: 2.0', 'largeSize: 2.0',
'textStyle: TextStyle(inherit: true, size: 4.0)', 'textStyle: TextStyle(inherit: true, size: 4.0)',
'padding: EdgeInsets.all(5.0)', 'padding: EdgeInsets.all(5.0)',
'alignment: AlignmentDirectional(6.0, 7.0)' 'alignment: AlignmentDirectional(6.0, 7.0)',
'offset: Offset(0.0, 0.0)'
]); ]);
}); });
...@@ -75,7 +78,8 @@ void main() { ...@@ -75,7 +78,8 @@ void main() {
largeSize: 20, largeSize: 20,
textStyle: TextStyle(fontSize: 12), textStyle: TextStyle(fontSize: 12),
padding: EdgeInsets.symmetric(horizontal: 5), padding: EdgeInsets.symmetric(horizontal: 5),
alignment: AlignmentDirectional(24, 0), alignment: Alignment.topRight,
offset: Offset(24, 0),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -95,8 +99,7 @@ void main() { ...@@ -95,8 +99,7 @@ void main() {
// text width = 48 = fontSize * 4, text height = fontSize // text width = 48 = fontSize * 4, text height = fontSize
expect(tester.getSize(find.text('1234')), const Size(48, 12)); expect(tester.getSize(find.text('1234')), const Size(48, 12));
// x = 29 = alignment.start + padding.left, y = 4 = (largeSize - fontSize) / 2 expect(tester.getTopLeft(find.text('1234')), const Offset(33, 4));
expect(tester.getTopLeft(find.text('1234')), const Offset(29, 4));
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
...@@ -107,8 +110,7 @@ void main() { ...@@ -107,8 +110,7 @@ void main() {
expect(textStyle.color, black); expect(textStyle.color, black);
final RenderBox box = tester.renderObject(find.byType(Badge)); final RenderBox box = tester.renderObject(find.byType(Badge));
// L = alignment.start, T = alignment.top, R = L + fontSize * 4 + padding.width, B = largeSize R = largeSize/2 expect(box, paints..rrect(rrect: RRect.fromLTRBR(28, 0, 86, 20, const Radius.circular(10)), color: green));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(24, 0, 82, 20, const Radius.circular(10)), color: green));
}); });
...@@ -125,7 +127,8 @@ void main() { ...@@ -125,7 +127,8 @@ void main() {
largeSize: 20, largeSize: 20,
textStyle: TextStyle(fontSize: 12), textStyle: TextStyle(fontSize: 12),
padding: EdgeInsets.symmetric(horizontal: 5), padding: EdgeInsets.symmetric(horizontal: 5),
alignment: AlignmentDirectional(24, 0), alignment: Alignment.topRight,
offset: Offset(24, 0),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -143,13 +146,13 @@ void main() { ...@@ -143,13 +146,13 @@ void main() {
); );
expect(tester.getSize(find.text('1234')), const Size(48, 12)); expect(tester.getSize(find.text('1234')), const Size(48, 12));
expect(tester.getTopLeft(find.text('1234')), const Offset(29, 4)); expect(tester.getTopLeft(find.text('1234')), const Offset(33, 4));
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
expect(tester.getTopLeft(find.byType(Badge)), Offset.zero); expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
final TextStyle textStyle = tester.renderObject<RenderParagraph>(find.text('1234')).text.style!; final TextStyle textStyle = tester.renderObject<RenderParagraph>(find.text('1234')).text.style!;
expect(textStyle.fontSize, 12); expect(textStyle.fontSize, 12);
expect(textStyle.color, black); expect(textStyle.color, black);
final RenderBox box = tester.renderObject(find.byType(Badge)); final RenderBox box = tester.renderObject(find.byType(Badge));
expect(box, paints..rrect(rrect: RRect.fromLTRBR(24, 0, 82, 20, const Radius.circular(10)), color: green)); expect(box, paints..rrect(rrect: RRect.fromLTRBR(28, 0, 86, 20, const Radius.circular(10)), color: green));
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment