@@ -104,7 +104,7 @@ class Checkbox extends StatefulWidget {
104104 /// design [Checkbox] .
105105 ///
106106 /// If a [CupertinoCheckbox] is created, the following parameters are ignored:
107- /// [mouseCursor] , [hoverColor] , [overlayColor] , [splashRadius] ,
107+ /// [mouseCursor] , [fillColor] , [ hoverColor] , [overlayColor] , [splashRadius] ,
108108 /// [materialTapTargetSize] , [visualDensity] , [isError] . However, [shape] and
109109 /// [side] will still affect the [CupertinoCheckbox] and should be handled if
110110 /// native fidelity is important.
@@ -452,10 +452,9 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin, Togg
452452 });
453453 }
454454
455- BorderSide ? _resolveSide (BorderSide ? side) {
455+ BorderSide ? _resolveSide (BorderSide ? side, Set < MaterialState > states ) {
456456 if (side is MaterialStateBorderSide ) {
457- final Set <MaterialState > sideStates = widget.isError ? (states..add (MaterialState .error)) : states;
458- return MaterialStateProperty .resolveAs <BorderSide ?>(side, sideStates);
457+ return MaterialStateProperty .resolveAs <BorderSide ?>(side, states);
459458 }
460459 if (! states.contains (MaterialState .selected)) {
461460 return side;
@@ -521,10 +520,12 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin, Togg
521520 });
522521
523522 // Colors need to be resolved in selected and non selected states separately
524- // so that they can be lerped between.
525- final Set <MaterialState > errorState = states..add (MaterialState .error);
526- final Set <MaterialState > activeStates = widget.isError ? (errorState..add (MaterialState .selected)) : states..add (MaterialState .selected);
527- final Set <MaterialState > inactiveStates = widget.isError ? (errorState..remove (MaterialState .selected)) : states..remove (MaterialState .selected);
523+ final Set <MaterialState > activeStates = states..add (MaterialState .selected);
524+ final Set <MaterialState > inactiveStates = states..remove (MaterialState .selected);
525+ if (widget.isError) {
526+ activeStates.add (MaterialState .error);
527+ inactiveStates.add (MaterialState .error);
528+ }
528529 final Color ? activeColor = widget.fillColor? .resolve (activeStates)
529530 ?? _widgetFillColor.resolve (activeStates)
530531 ?? checkboxTheme.fillColor? .resolve (activeStates);
@@ -536,13 +537,26 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin, Togg
536537 final Color effectiveInactiveColor = inactiveColor
537538 ?? defaults.fillColor! .resolve (inactiveStates)! ;
538539
539- final Set <MaterialState > focusedStates = widget.isError ? (errorState..add (MaterialState .focused)) : states..add (MaterialState .focused);
540+ final BorderSide activeSide = _resolveSide (widget.side, activeStates)
541+ ?? _resolveSide (checkboxTheme.side, activeStates)
542+ ?? _resolveSide (defaults.side, activeStates)! ;
543+ final BorderSide inactiveSide = _resolveSide (widget.side, inactiveStates)
544+ ?? _resolveSide (checkboxTheme.side, inactiveStates)
545+ ?? _resolveSide (defaults.side, inactiveStates)! ;
546+
547+ final Set <MaterialState > focusedStates = states..add (MaterialState .focused);
548+ if (widget.isError) {
549+ focusedStates.add (MaterialState .error);
550+ }
540551 Color effectiveFocusOverlayColor = widget.overlayColor? .resolve (focusedStates)
541552 ?? widget.focusColor
542553 ?? checkboxTheme.overlayColor? .resolve (focusedStates)
543554 ?? defaults.overlayColor! .resolve (focusedStates)! ;
544555
545- final Set <MaterialState > hoveredStates = widget.isError ? (errorState..add (MaterialState .hovered)) : states..add (MaterialState .hovered);
556+ final Set <MaterialState > hoveredStates = states..add (MaterialState .hovered);
557+ if (widget.isError) {
558+ hoveredStates.add (MaterialState .error);
559+ }
546560 Color effectiveHoverOverlayColor = widget.overlayColor? .resolve (hoveredStates)
547561 ?? widget.hoverColor
548562 ?? checkboxTheme.overlayColor? .resolve (hoveredStates)
@@ -606,7 +620,8 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin, Togg
606620 ..value = value
607621 ..previousValue = _previousValue
608622 ..shape = widget.shape ?? checkboxTheme.shape ?? defaults.shape!
609- ..side = _resolveSide (widget.side) ?? _resolveSide (checkboxTheme.side),
623+ ..activeSide = activeSide
624+ ..inactiveSide = inactiveSide,
610625 ),
611626 );
612627 }
@@ -656,13 +671,23 @@ class _CheckboxPainter extends ToggleablePainter {
656671 notifyListeners ();
657672 }
658673
659- BorderSide ? get side => _side ;
660- BorderSide ? _side ;
661- set side (BorderSide ? value) {
662- if (_side == value) {
674+ BorderSide get activeSide => _activeSide ! ;
675+ BorderSide ? _activeSide ;
676+ set activeSide (BorderSide value) {
677+ if (_activeSide == value) {
663678 return ;
664679 }
665- _side = value;
680+ _activeSide = value;
681+ notifyListeners ();
682+ }
683+
684+ BorderSide get inactiveSide => _inactiveSide! ;
685+ BorderSide ? _inactiveSide;
686+ set inactiveSide (BorderSide value) {
687+ if (_inactiveSide == value) {
688+ return ;
689+ }
690+ _inactiveSide = value;
666691 notifyListeners ();
667692 }
668693
@@ -677,8 +702,7 @@ class _CheckboxPainter extends ToggleablePainter {
677702 return rect;
678703 }
679704
680- // The checkbox's border color if value == false, or its fill color when
681- // value == true or null.
705+ // The checkbox's fill color
682706 Color _colorAt (double t) {
683707 // As t goes from 0.0 to 0.25, animate from the inactiveColor to activeColor.
684708 return t >= 0.25 ? activeColor : Color .lerp (inactiveColor, activeColor, t * 4.0 )! ;
@@ -692,10 +716,8 @@ class _CheckboxPainter extends ToggleablePainter {
692716 ..strokeWidth = _kStrokeWidth;
693717 }
694718
695- void _drawBox (Canvas canvas, Rect outer, Paint paint, BorderSide ? side, bool fill) {
696- if (fill) {
697- canvas.drawPath (shape.getOuterPath (outer), paint);
698- }
719+ void _drawBox (Canvas canvas, Rect outer, Paint paint, BorderSide ? side) {
720+ canvas.drawPath (shape.getOuterPath (outer), paint);
699721 if (side != null ) {
700722 shape.copyWith (side: side).paint (canvas, outer);
701723 }
@@ -754,10 +776,10 @@ class _CheckboxPainter extends ToggleablePainter {
754776 final Paint paint = Paint ()..color = _colorAt (t);
755777
756778 if (t <= 0.5 ) {
757- final BorderSide border = side ?? BorderSide (width : 2 , color : paint.color );
758- _drawBox (canvas, outer, paint, border, false ); // only paint the border
779+ final BorderSide border = BorderSide . lerp (inactiveSide, activeSide, t );
780+ _drawBox (canvas, outer, paint, border);
759781 } else {
760- _drawBox (canvas, outer, paint, side, true );
782+ _drawBox (canvas, outer, paint, activeSide );
761783 final double tShrink = (t - 0.5 ) * 2.0 ;
762784 if (previousValue == null || value == null ) {
763785 _drawDash (canvas, origin, tShrink, strokePaint);
@@ -769,7 +791,7 @@ class _CheckboxPainter extends ToggleablePainter {
769791 final Rect outer = _outerRectAt (origin, 1.0 );
770792 final Paint paint = Paint () ..color = _colorAt (1.0 );
771793
772- _drawBox (canvas, outer, paint, side, true );
794+ _drawBox (canvas, outer, paint, activeSide );
773795 if (tNormalized <= 0.5 ) {
774796 final double tShrink = 1.0 - tNormalized * 2.0 ;
775797 if (previousValue ?? false ) {
@@ -798,16 +820,35 @@ class _CheckboxDefaultsM2 extends CheckboxThemeData {
798820 final ThemeData _theme;
799821 final ColorScheme _colors;
800822
823+ @override
824+ MaterialStateBorderSide ? get side {
825+ return MaterialStateBorderSide .resolveWith ((Set <MaterialState > states) {
826+ if (states.contains (MaterialState .disabled)) {
827+ if (states.contains (MaterialState .selected)) {
828+ return const BorderSide (width: 2.0 , color: Colors .transparent);
829+ }
830+ return BorderSide (width: 2.0 , color: _theme.disabledColor);
831+ }
832+ if (states.contains (MaterialState .selected)) {
833+ return const BorderSide (width: 2.0 , color: Colors .transparent);
834+ }
835+ return BorderSide (width: 2.0 , color: _theme.unselectedWidgetColor);
836+ });
837+ }
838+
801839 @override
802840 MaterialStateProperty <Color > get fillColor {
803841 return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
804842 if (states.contains (MaterialState .disabled)) {
805- return _theme.disabledColor;
843+ if (states.contains (MaterialState .selected)) {
844+ return _theme.disabledColor;
845+ }
846+ return Colors .transparent;
806847 }
807848 if (states.contains (MaterialState .selected)) {
808849 return _colors.secondary;
809850 }
810- return _theme.unselectedWidgetColor ;
851+ return Colors .transparent ;
811852 });
812853 }
813854
@@ -865,27 +906,49 @@ class _CheckboxDefaultsM3 extends CheckboxThemeData {
865906 final ColorScheme _colors;
866907
867908 @override
868- MaterialStateProperty < Color > get fillColor {
869- return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
909+ MaterialStateBorderSide ? get side {
910+ return MaterialStateBorderSide .resolveWith ((Set <MaterialState > states) {
870911 if (states.contains (MaterialState .disabled)) {
871- return _colors.onSurface. withOpacity ( 0.38 );
872- }
873- if (states. contains ( MaterialState .error)) {
874- return _colors.error ;
912+ if (states. contains ( MaterialState .selected)) {
913+ return const BorderSide (width : 2.0 , color : Colors .transparent);
914+ }
915+ return BorderSide (width : 2.0 , color : _colors.onSurface. withOpacity ( 0.38 )) ;
875916 }
876917 if (states.contains (MaterialState .selected)) {
877- return _colors.primary;
918+ return const BorderSide (width: 0.0 , color: Colors .transparent);
919+ }
920+ if (states.contains (MaterialState .error)) {
921+ return BorderSide (width: 2.0 , color: _colors.error);
878922 }
879923 if (states.contains (MaterialState .pressed)) {
880- return _colors.onSurface;
924+ return BorderSide (width : 2.0 , color : _colors.onSurface) ;
881925 }
882926 if (states.contains (MaterialState .hovered)) {
883- return _colors.onSurface;
927+ return BorderSide (width : 2.0 , color : _colors.onSurface) ;
884928 }
885929 if (states.contains (MaterialState .focused)) {
886- return _colors.onSurface;
930+ return BorderSide (width : 2.0 , color : _colors.onSurface) ;
887931 }
888- return _colors.onSurfaceVariant;
932+ return BorderSide (width: 2.0 , color: _colors.onSurfaceVariant);
933+ });
934+ }
935+
936+ @override
937+ MaterialStateProperty <Color > get fillColor {
938+ return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
939+ if (states.contains (MaterialState .disabled)) {
940+ if (states.contains (MaterialState .selected)) {
941+ return _colors.onSurface.withOpacity (0.38 );
942+ }
943+ return Colors .transparent;
944+ }
945+ if (states.contains (MaterialState .selected)) {
946+ if (states.contains (MaterialState .error)) {
947+ return _colors.error;
948+ }
949+ return _colors.primary;
950+ }
951+ return Colors .transparent;
889952 });
890953 }
891954
0 commit comments