Unverified Commit 21b27088 authored by Yash Johri's avatar Yash Johri Committed by GitHub

[Checkbox] Adds shape property (#70171)

parent 8104c578
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
// 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 'dart:math' as math; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -71,6 +72,8 @@ class Checkbox extends StatefulWidget { ...@@ -71,6 +72,8 @@ class Checkbox extends StatefulWidget {
this.visualDensity, this.visualDensity,
this.focusNode, this.focusNode,
this.autofocus = false, this.autofocus = false,
this.shape,
this.side,
}) : assert(tristate != null), }) : assert(tristate != null),
assert(tristate || value != null), assert(tristate || value != null),
assert(autofocus != null), assert(autofocus != null),
...@@ -263,6 +266,23 @@ class Checkbox extends StatefulWidget { ...@@ -263,6 +266,23 @@ class Checkbox extends StatefulWidget {
/// {@macro flutter.widgets.Focus.autofocus} /// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus; final bool autofocus;
/// {@template flutter.material.checkbox.shape}
/// The shape of the checkbox's [Material].
/// {@endtemplate}
///
/// If this property is null then [CheckboxThemeData.shape] of [ThemeData.checkboxTheme]
/// is used. If that's null then the shape will be a [RoundedRectangleBorder]
/// with a circular corner radius of 1.0.
final OutlinedBorder? shape;
/// {@template flutter.material.checkbox.side}
/// The side of the checkbox's border.
/// {@endtemplate}
///
/// If this property is null then [CheckboxThemeData.side] of [ThemeData.checkboxTheme]
/// is used. If that's null then the side will be width 2.
final BorderSide? side;
/// The width of a checkbox widget. /// The width of a checkbox widget.
static const double width = 18.0; static const double width = 18.0;
...@@ -435,6 +455,10 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin { ...@@ -435,6 +455,10 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin {
vsync: this, vsync: this,
hasFocus: _focused, hasFocus: _focused,
hovering: _hovering, hovering: _hovering,
side: widget.side ?? themeData.checkboxTheme.side,
shape: widget.shape ?? themeData.checkboxTheme.shape ?? const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(1.0)),
),
); );
}, },
), ),
...@@ -460,6 +484,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -460,6 +484,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
required this.additionalConstraints, required this.additionalConstraints,
required this.hasFocus, required this.hasFocus,
required this.hovering, required this.hovering,
required this.shape,
required this.side,
}) : assert(tristate != null), }) : assert(tristate != null),
assert(tristate || value != null), assert(tristate || value != null),
assert(activeColor != null), assert(activeColor != null),
...@@ -482,6 +508,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -482,6 +508,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
final ValueChanged<bool?>? onChanged; final ValueChanged<bool?>? onChanged;
final TickerProvider vsync; final TickerProvider vsync;
final BoxConstraints additionalConstraints; final BoxConstraints additionalConstraints;
final OutlinedBorder shape;
final BorderSide? side;
@override @override
_RenderCheckbox createRenderObject(BuildContext context) => _RenderCheckbox( _RenderCheckbox createRenderObject(BuildContext context) => _RenderCheckbox(
...@@ -500,6 +528,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -500,6 +528,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
additionalConstraints: additionalConstraints, additionalConstraints: additionalConstraints,
hasFocus: hasFocus, hasFocus: hasFocus,
hovering: hovering, hovering: hovering,
shape: shape,
side: side,
); );
@override @override
...@@ -521,12 +551,13 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -521,12 +551,13 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
..additionalConstraints = additionalConstraints ..additionalConstraints = additionalConstraints
..vsync = vsync ..vsync = vsync
..hasFocus = hasFocus ..hasFocus = hasFocus
..hovering = hovering; ..hovering = hovering
..shape = shape
..side = side;
} }
} }
const double _kEdgeSize = Checkbox.width; const double _kEdgeSize = Checkbox.width;
const Radius _kEdgeRadius = Radius.circular(1.0);
const double _kStrokeWidth = 2.0; const double _kStrokeWidth = 2.0;
class _RenderCheckbox extends RenderToggleable { class _RenderCheckbox extends RenderToggleable {
...@@ -545,6 +576,8 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -545,6 +576,8 @@ class _RenderCheckbox extends RenderToggleable {
ValueChanged<bool?>? onChanged, ValueChanged<bool?>? onChanged,
required bool hasFocus, required bool hasFocus,
required bool hovering, required bool hovering,
required this.shape,
required this.side,
required TickerProvider vsync, required TickerProvider vsync,
}) : _oldValue = value, }) : _oldValue = value,
super( super(
...@@ -566,6 +599,8 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -566,6 +599,8 @@ class _RenderCheckbox extends RenderToggleable {
bool? _oldValue; bool? _oldValue;
Color checkColor; Color checkColor;
OutlinedBorder shape;
BorderSide? side;
@override @override
set value(bool? newValue) { set value(bool? newValue) {
...@@ -585,11 +620,11 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -585,11 +620,11 @@ class _RenderCheckbox extends RenderToggleable {
// At t == 0.0, the outer rect's size is _kEdgeSize (Checkbox.width) // At t == 0.0, the outer rect's size is _kEdgeSize (Checkbox.width)
// At t == 0.5, .. is _kEdgeSize - _kStrokeWidth // At t == 0.5, .. is _kEdgeSize - _kStrokeWidth
// At t == 1.0, .. is _kEdgeSize // At t == 1.0, .. is _kEdgeSize
RRect _outerRectAt(Offset origin, double t) { Rect _outerRectAt(Offset origin, double t) {
final double inset = 1.0 - (t - 0.5).abs() * 2.0; final double inset = 1.0 - (t - 0.5).abs() * 2.0;
final double size = _kEdgeSize - inset * _kStrokeWidth; final double size = _kEdgeSize - inset * _kStrokeWidth;
final Rect rect = Rect.fromLTWH(origin.dx + inset, origin.dy + inset, size, size); final Rect rect = Rect.fromLTWH(origin.dx + inset, origin.dy + inset, size, size);
return RRect.fromRectAndRadius(rect, _kEdgeRadius); return rect;
} }
// The checkbox's border color if value == false, or its fill color when // The checkbox's border color if value == false, or its fill color when
...@@ -607,12 +642,12 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -607,12 +642,12 @@ class _RenderCheckbox extends RenderToggleable {
..strokeWidth = _kStrokeWidth; ..strokeWidth = _kStrokeWidth;
} }
void _drawBorder(Canvas canvas, RRect outer, double t, Paint paint) { void _drawBorder(Canvas canvas, Rect outer, double t, Paint paint) {
assert(t >= 0.0 && t <= 0.5); assert(t >= 0.0 && t <= 0.5);
final double size = outer.width; if (side == null) {
// As t goes from 0.0 to 1.0, gradually fill the outer RRect. shape = shape.copyWith(side: BorderSide(width: 2, color: paint.color));
final RRect inner = outer.deflate(math.min(size / 2.0, _kStrokeWidth + size * t)); }
canvas.drawDRRect(outer, inner, paint); shape.copyWith(side: side).paint(canvas, outer);
} }
void _drawCheck(Canvas canvas, Offset origin, double t, Paint paint) { void _drawCheck(Canvas canvas, Offset origin, double t, Paint paint) {
...@@ -665,13 +700,14 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -665,13 +700,14 @@ class _RenderCheckbox extends RenderToggleable {
// Four cases: false to null, false to true, null to false, true to false // Four cases: false to null, false to true, null to false, true to false
if (_oldValue == false || value == false) { if (_oldValue == false || value == false) {
final double t = value == false ? 1.0 - tNormalized : tNormalized; final double t = value == false ? 1.0 - tNormalized : tNormalized;
final RRect outer = _outerRectAt(origin, t); final Rect outer = _outerRectAt(origin, t);
final Path emptyCheckboxPath = shape.copyWith(side: side).getOuterPath(outer);
final Paint paint = Paint()..color = _colorAt(t); final Paint paint = Paint()..color = _colorAt(t);
if (t <= 0.5) { if (t <= 0.5) {
_drawBorder(canvas, outer, t, paint); _drawBorder(canvas, outer, t, paint);
} else { } else {
canvas.drawRRect(outer, paint); canvas.drawPath(emptyCheckboxPath, paint);
final double tShrink = (t - 0.5) * 2.0; final double tShrink = (t - 0.5) * 2.0;
if (_oldValue == null || value == null) if (_oldValue == null || value == null)
...@@ -680,9 +716,9 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -680,9 +716,9 @@ class _RenderCheckbox extends RenderToggleable {
_drawCheck(canvas, origin, tShrink, strokePaint); _drawCheck(canvas, origin, tShrink, strokePaint);
} }
} else { // Two cases: null to true, true to null } else { // Two cases: null to true, true to null
final RRect outer = _outerRectAt(origin, 1.0); final Rect outer = _outerRectAt(origin, 1.0);
final Paint paint = Paint() ..color = _colorAt(1.0); final Paint paint = Paint() ..color = _colorAt(1.0);
canvas.drawRRect(outer, paint); canvas.drawPath(shape.copyWith(side: side).getOuterPath(outer), paint);
if (tNormalized <= 0.5) { if (tNormalized <= 0.5) {
final double tShrink = 1.0 - tNormalized * 2.0; final double tShrink = 1.0 - tNormalized * 2.0;
......
...@@ -41,6 +41,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -41,6 +41,8 @@ class CheckboxThemeData with Diagnosticable {
this.splashRadius, this.splashRadius,
this.materialTapTargetSize, this.materialTapTargetSize,
this.visualDensity, this.visualDensity,
this.shape,
this.side,
}); });
/// {@macro flutter.material.checkbox.mouseCursor} /// {@macro flutter.material.checkbox.mouseCursor}
...@@ -85,6 +87,16 @@ class CheckboxThemeData with Diagnosticable { ...@@ -85,6 +87,16 @@ class CheckboxThemeData with Diagnosticable {
/// If specified, overrides the default value of [Checkbox.visualDensity]. /// If specified, overrides the default value of [Checkbox.visualDensity].
final VisualDensity? visualDensity; final VisualDensity? visualDensity;
/// {@macro flutter.material.checkbox.shape}
///
/// If specified, overrides the default value of [Checkbox.shape].
final OutlinedBorder? shape;
/// {@macro flutter.material.checkbox.side}
///
/// If specified, overrides the default value of [Checkbox.side].
final BorderSide? side;
/// 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.
CheckboxThemeData copyWith({ CheckboxThemeData copyWith({
...@@ -95,6 +107,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -95,6 +107,8 @@ class CheckboxThemeData with Diagnosticable {
double? splashRadius, double? splashRadius,
MaterialTapTargetSize? materialTapTargetSize, MaterialTapTargetSize? materialTapTargetSize,
VisualDensity? visualDensity, VisualDensity? visualDensity,
OutlinedBorder? shape,
BorderSide? side,
}) { }) {
return CheckboxThemeData( return CheckboxThemeData(
mouseCursor: mouseCursor ?? this.mouseCursor, mouseCursor: mouseCursor ?? this.mouseCursor,
...@@ -104,6 +118,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -104,6 +118,8 @@ class CheckboxThemeData with Diagnosticable {
splashRadius: splashRadius ?? this.splashRadius, splashRadius: splashRadius ?? this.splashRadius,
materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize, materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize,
visualDensity: visualDensity ?? this.visualDensity, visualDensity: visualDensity ?? this.visualDensity,
shape: shape ?? this.shape,
side: side ?? this.side,
); );
} }
...@@ -119,6 +135,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -119,6 +135,8 @@ class CheckboxThemeData with Diagnosticable {
splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t), splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize, materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize,
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity, visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
shape: ShapeBorder.lerp(a?.shape, b?.shape, t) as OutlinedBorder?,
side: _lerpSides(a?.side, b?.side, t),
); );
} }
...@@ -132,6 +150,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -132,6 +150,8 @@ class CheckboxThemeData with Diagnosticable {
splashRadius, splashRadius,
materialTapTargetSize, materialTapTargetSize,
visualDensity, visualDensity,
shape,
side,
); );
} }
...@@ -148,7 +168,9 @@ class CheckboxThemeData with Diagnosticable { ...@@ -148,7 +168,9 @@ class CheckboxThemeData with Diagnosticable {
&& other.overlayColor == overlayColor && other.overlayColor == overlayColor
&& other.splashRadius == splashRadius && other.splashRadius == splashRadius
&& other.materialTapTargetSize == materialTapTargetSize && other.materialTapTargetSize == materialTapTargetSize
&& other.visualDensity == visualDensity; && other.visualDensity == visualDensity
&& other.shape == shape
&& other.side == side;
} }
@override @override
...@@ -161,6 +183,8 @@ class CheckboxThemeData with Diagnosticable { ...@@ -161,6 +183,8 @@ class CheckboxThemeData with Diagnosticable {
properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null)); properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null));
properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null)); properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null));
properties.add(DiagnosticsProperty<OutlinedBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<BorderSide>('side', side, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>( static MaterialStateProperty<T>? _lerpProperties<T>(
...@@ -174,6 +198,13 @@ class CheckboxThemeData with Diagnosticable { ...@@ -174,6 +198,13 @@ class CheckboxThemeData with Diagnosticable {
return null; return null;
return _LerpProperties<T>(a, b, t, lerpFunction); return _LerpProperties<T>(a, b, t, lerpFunction);
} }
// Special case because BorderSide.lerp() doesn't support null arguments
static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) {
if (a == null && b == null)
return null;
return BorderSide.lerp(a!, b!, t);
}
} }
class _LerpProperties<T> implements MaterialStateProperty<T> { class _LerpProperties<T> implements MaterialStateProperty<T> {
......
...@@ -34,6 +34,9 @@ void main() { ...@@ -34,6 +34,9 @@ void main() {
}); });
testWidgets('CheckboxListTile checkColor test', (WidgetTester tester) async { testWidgets('CheckboxListTile checkColor test', (WidgetTester tester) async {
const Color checkBoxBorderColor = Color(0xff1e88e5);
Color checkBoxCheckColor = const Color(0xffFFFFFF);
Widget buildFrame(Color? color) { Widget buildFrame(Color? color) {
return wrap( return wrap(
child: CheckboxListTile( child: CheckboxListTile(
...@@ -50,11 +53,13 @@ void main() { ...@@ -50,11 +53,13 @@ void main() {
await tester.pumpWidget(buildFrame(null)); await tester.pumpWidget(buildFrame(null));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFFFFFFFF))); expect(getCheckboxListTileRenderer(), paints..path(color: checkBoxBorderColor)..path(color: checkBoxCheckColor));
checkBoxCheckColor = const Color(0xFF000000);
await tester.pumpWidget(buildFrame(const Color(0xFF000000))); await tester.pumpWidget(buildFrame(checkBoxCheckColor));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFF000000))); expect(getCheckboxListTileRenderer(), paints..path(color: checkBoxBorderColor)..path(color: checkBoxCheckColor));
}); });
testWidgets('CheckboxListTile activeColor test', (WidgetTester tester) async { testWidgets('CheckboxListTile activeColor test', (WidgetTester tester) async {
...@@ -76,11 +81,11 @@ void main() { ...@@ -76,11 +81,11 @@ void main() {
await tester.pumpWidget(buildFrame(const Color(0xFF000000), null)); await tester.pumpWidget(buildFrame(const Color(0xFF000000), null));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..rrect(color: const Color(0xFF000000))); expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFF000000)));
await tester.pumpWidget(buildFrame(const Color(0xFF000000), const Color(0xFFFFFFFF))); await tester.pumpWidget(buildFrame(const Color(0xFF000000), const Color(0xFFFFFFFF)));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxListTileRenderer(), paints..rrect(color: const Color(0xFFFFFFFF))); expect(getCheckboxListTileRenderer(), paints..path(color: const Color(0xFFFFFFFF)));
}); });
testWidgets('CheckboxListTile can autofocus unless disabled.', (WidgetTester tester) async { testWidgets('CheckboxListTile can autofocus unless disabled.', (WidgetTester tester) async {
......
...@@ -355,6 +355,10 @@ void main() { ...@@ -355,6 +355,10 @@ void main() {
}); });
testWidgets('CheckBox color rendering', (WidgetTester tester) async { testWidgets('CheckBox color rendering', (WidgetTester tester) async {
const Color borderColor = Color(0xff1e88e5);
Color checkColor = const Color(0xffFFFFFF);
Color activeColor;
Widget buildFrame({Color? activeColor, Color? checkColor, ThemeData? themeData}) { Widget buildFrame({Color? activeColor, Color? checkColor, ThemeData? themeData}) {
return Material( return Material(
child: Theme( child: Theme(
...@@ -379,21 +383,27 @@ void main() { ...@@ -379,21 +383,27 @@ void main() {
})); }));
} }
await tester.pumpWidget(buildFrame(checkColor: const Color(0xFFFFFFFF))); await tester.pumpWidget(buildFrame(checkColor: checkColor));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..path(color: const Color(0xFFFFFFFF))); // paints's color is 0xFFFFFFFF (default color) expect(getCheckboxRenderer(), paints..path(color: borderColor)..path(color: checkColor)); // paints's color is 0xFFFFFFFF (default color)
checkColor = const Color(0xFF000000);
await tester.pumpWidget(buildFrame(checkColor: const Color(0xFF000000))); await tester.pumpWidget(buildFrame(checkColor: checkColor));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..path(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (params) expect(getCheckboxRenderer(), paints..path(color: borderColor)..path(color: checkColor)); // paints's color is 0xFF000000 (params)
activeColor = const Color(0xFF00FF00);
await tester.pumpWidget(buildFrame(themeData: ThemeData(toggleableActiveColor: const Color(0xFF00FF00)))); await tester.pumpWidget(buildFrame(themeData: ThemeData(toggleableActiveColor: activeColor)));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: const Color(0xFF00FF00))); // paints's color is 0xFF00FF00 (theme) expect(getCheckboxRenderer(), paints..path(color: activeColor)); // paints's color is 0xFF00FF00 (theme)
await tester.pumpWidget(buildFrame(activeColor: const Color(0xFF000000))); activeColor = const Color(0xFF000000);
await tester.pumpWidget(buildFrame(activeColor: activeColor));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: const Color(0xFF000000))); // paints's color is 0xFF000000 (params) expect(getCheckboxRenderer(), paints..path(color: activeColor)); // paints's color is 0xFF000000 (params)
}); });
testWidgets('Checkbox is focusable and has correct focus color', (WidgetTester tester) async { testWidgets('Checkbox is focusable and has correct focus color', (WidgetTester tester) async {
...@@ -429,10 +439,7 @@ void main() { ...@@ -429,10 +439,7 @@ void main() {
Material.of(tester.element(find.byType(Checkbox))), Material.of(tester.element(find.byType(Checkbox))),
paints paints
..circle(color: Colors.orange[500]) ..circle(color: Colors.orange[500])
..rrect( ..path(color: const Color(0xff1e88e5))
color: const Color(0xff1e88e5),
rrect: RRect.fromLTRBR(
391.0, 291.0, 409.0, 309.0, const Radius.circular(1.0)))
..path(color: Colors.white), ..path(color: Colors.white),
); );
...@@ -525,11 +532,8 @@ void main() { ...@@ -525,11 +532,8 @@ void main() {
expect( expect(
Material.of(tester.element(find.byType(Checkbox))), Material.of(tester.element(find.byType(Checkbox))),
paints paints
..rrect( ..path(color: const Color(0xff1e88e5))
color: const Color(0xff1e88e5), ..path(color: const Color(0xffffffff),style: PaintingStyle.stroke, strokeWidth: 2.0),
rrect: RRect.fromLTRBR(
391.0, 291.0, 409.0, 309.0, const Radius.circular(1.0)))
..path(color: const Color(0xffffffff), style: PaintingStyle.stroke, strokeWidth: 2.0),
); );
// Start hovering // Start hovering
...@@ -542,10 +546,7 @@ void main() { ...@@ -542,10 +546,7 @@ void main() {
expect( expect(
Material.of(tester.element(find.byType(Checkbox))), Material.of(tester.element(find.byType(Checkbox))),
paints paints
..rrect( ..path(color: const Color(0xff1e88e5))
color: const Color(0xff1e88e5),
rrect: RRect.fromLTRBR(
391.0, 291.0, 409.0, 309.0, const Radius.circular(1.0)))
..path(color: const Color(0xffffffff), style: PaintingStyle.stroke, strokeWidth: 2.0), ..path(color: const Color(0xffffffff), style: PaintingStyle.stroke, strokeWidth: 2.0),
); );
...@@ -555,10 +556,7 @@ void main() { ...@@ -555,10 +556,7 @@ void main() {
expect( expect(
Material.of(tester.element(find.byType(Checkbox))), Material.of(tester.element(find.byType(Checkbox))),
paints paints
..rrect( ..path(color: const Color(0x61000000))
color: const Color(0x61000000),
rrect: RRect.fromLTRBR(
391.0, 291.0, 409.0, 309.0, const Radius.circular(1.0)))
..path(color: const Color(0xffffffff), style: PaintingStyle.stroke, strokeWidth: 2.0), ..path(color: const Color(0xffffffff), style: PaintingStyle.stroke, strokeWidth: 2.0),
); );
}); });
...@@ -835,11 +833,11 @@ void main() { ...@@ -835,11 +833,11 @@ void main() {
await tester.pumpWidget(buildFrame(enabled: true)); await tester.pumpWidget(buildFrame(enabled: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: activeEnabledFillColor)); expect(getCheckboxRenderer(), paints..path(color: activeEnabledFillColor));
await tester.pumpWidget(buildFrame(enabled: false)); await tester.pumpWidget(buildFrame(enabled: false));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: activeDisabledFillColor)); expect(getCheckboxRenderer(), paints..path(color: activeDisabledFillColor));
}); });
testWidgets('Checkbox fill color resolves in hovered/focused states', (WidgetTester tester) async { testWidgets('Checkbox fill color resolves in hovered/focused states', (WidgetTester tester) async {
...@@ -889,7 +887,7 @@ void main() { ...@@ -889,7 +887,7 @@ void main() {
await tester.pumpWidget(buildFrame()); await tester.pumpWidget(buildFrame());
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isTrue); expect(focusNode.hasPrimaryFocus, isTrue);
expect(getCheckboxRenderer(), paints..rrect(color: focusedFillColor)); expect(getCheckboxRenderer(), paints..path(color: focusedFillColor));
// Start hovering // Start hovering
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
...@@ -898,7 +896,53 @@ void main() { ...@@ -898,7 +896,53 @@ void main() {
await gesture.moveTo(tester.getCenter(find.byType(Checkbox))); await gesture.moveTo(tester.getCenter(find.byType(Checkbox)));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getCheckboxRenderer(), paints..rrect(color: hoveredFillColor)); expect(getCheckboxRenderer(), paints..path(color: hoveredFillColor));
});
testWidgets('Checkbox respects shape and side', (WidgetTester tester) async {
final RoundedRectangleBorder roundedRectangleBorder =
RoundedRectangleBorder(borderRadius: BorderRadius.circular(5));
const BorderSide side = BorderSide(
width: 4,
color: Color(0xfff44336),
);
Widget buildApp() {
return MaterialApp(
home: Material(
child: Center(
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Checkbox(
value: false,
onChanged: (bool? newValue) {},
shape: roundedRectangleBorder,
side: side,
);
}),
),
),
);
}
await tester.pumpWidget(buildApp());
await tester.pumpAndSettle();
expect(tester.widget<Checkbox>(find.byType(Checkbox)).shape,
roundedRectangleBorder);
expect(tester.widget<Checkbox>(find.byType(Checkbox)).side, side);
expect(
Material.of(tester.element(find.byType(Checkbox))),
paints
..drrect(
color: const Color(0xfff44336),
outer: RRect.fromLTRBR(
391.0, 291.0, 409.0, 309.0, const Radius.circular(5)),
inner: RRect.fromLTRBR(
395.0, 295.0, 405.0, 305.0, const Radius.circular(1)))
,
);
}); });
testWidgets('Checkbox overlay color resolves in active/pressed/focused/hovered states', (WidgetTester tester) async { testWidgets('Checkbox overlay color resolves in active/pressed/focused/hovered states', (WidgetTester tester) async {
......
...@@ -138,8 +138,8 @@ void main() { ...@@ -138,8 +138,8 @@ void main() {
// Selected checkbox. // Selected checkbox.
await tester.pumpWidget(buildCheckbox(selected: true)); await tester.pumpWidget(buildCheckbox(selected: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(_getCheckboxMaterial(tester), paints..rrect(color: selectedFillColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor));
expect(_getCheckboxMaterial(tester), paints..path(color: defaultCheckColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor)..path(color: defaultCheckColor));
// Checkbox with hover. // Checkbox with hover.
await tester.pumpWidget(buildCheckbox()); await tester.pumpWidget(buildCheckbox());
...@@ -152,7 +152,7 @@ void main() { ...@@ -152,7 +152,7 @@ void main() {
await tester.pumpWidget(buildCheckbox(autofocus: true, selected: true)); await tester.pumpWidget(buildCheckbox(autofocus: true, selected: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(_getCheckboxMaterial(tester), paints..circle(color: focusOverlayColor, radius: splashRadius)); expect(_getCheckboxMaterial(tester), paints..circle(color: focusOverlayColor, radius: splashRadius));
expect(_getCheckboxMaterial(tester), paints..path(color: focusedCheckColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor)..path(color: focusedCheckColor));
}); });
testWidgets('Checkbox properties are taken over the theme values', (WidgetTester tester) async { testWidgets('Checkbox properties are taken over the theme values', (WidgetTester tester) async {
...@@ -237,8 +237,8 @@ void main() { ...@@ -237,8 +237,8 @@ void main() {
// Selected checkbox. // Selected checkbox.
await tester.pumpWidget(buildCheckbox(selected: true)); await tester.pumpWidget(buildCheckbox(selected: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(_getCheckboxMaterial(tester), paints..rrect(color: selectedFillColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor));
expect(_getCheckboxMaterial(tester), paints..path(color: checkColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor)..path(color: checkColor));
// Checkbox with hover. // Checkbox with hover.
await tester.pumpWidget(buildCheckbox()); await tester.pumpWidget(buildCheckbox());
...@@ -288,7 +288,7 @@ void main() { ...@@ -288,7 +288,7 @@ void main() {
// Selected checkbox. // Selected checkbox.
await tester.pumpWidget(buildCheckbox(selected: true)); await tester.pumpWidget(buildCheckbox(selected: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(_getCheckboxMaterial(tester), paints..rrect(color: selectedFillColor)); expect(_getCheckboxMaterial(tester), paints..path(color: selectedFillColor));
}); });
testWidgets('Checkbox theme overlay color resolves in active/pressed states', (WidgetTester tester) async { testWidgets('Checkbox theme overlay color resolves in active/pressed states', (WidgetTester tester) async {
......
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