diff --git a/packages/flutter/lib/src/material/button_style.dart b/packages/flutter/lib/src/material/button_style.dart index 7bcac2fa73c..43641d2ac8a 100644 --- a/packages/flutter/lib/src/material/button_style.dart +++ b/packages/flutter/lib/src/material/button_style.dart @@ -776,7 +776,7 @@ class ButtonStyle with Diagnosticable { iconColor: MaterialStateProperty.lerp(a?.iconColor, b?.iconColor, t, Color.lerp), iconSize: MaterialStateProperty.lerp(a?.iconSize, b?.iconSize, t, lerpDouble), iconAlignment: t < 0.5 ? a?.iconAlignment : b?.iconAlignment, - side: _lerpSides(a?.side, b?.side, t), + side: WidgetStateBorderSide.lerp(a?.side, b?.side, t), shape: MaterialStateProperty.lerp( a?.shape, b?.shape, @@ -794,16 +794,4 @@ class ButtonStyle with Diagnosticable { foregroundBuilder: t < 0.5 ? a?.foregroundBuilder : b?.foregroundBuilder, ); } - - // Special case because BorderSide.lerp() doesn't support null arguments - static MaterialStateProperty? _lerpSides( - MaterialStateProperty? a, - MaterialStateProperty? b, - double t, - ) { - if (a == null && b == null) { - return null; - } - return MaterialStateBorderSide.lerp(a, b, t); - } } diff --git a/packages/flutter/lib/src/material/checkbox_theme.dart b/packages/flutter/lib/src/material/checkbox_theme.dart index a63c3fae8ec..3a964f5ac5f 100644 --- a/packages/flutter/lib/src/material/checkbox_theme.dart +++ b/packages/flutter/lib/src/material/checkbox_theme.dart @@ -235,19 +235,19 @@ class CheckboxThemeData with Diagnosticable { // Special case because BorderSide.lerp() doesn't support null arguments static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) { - if (a == null || b == null) { + if (a == null && b == null) { return null; } - if (identical(a, b)) { - return a; + if (a is WidgetStateBorderSide) { + a = a.resolve(const {}); } - if (a is MaterialStateBorderSide) { - a = a.resolve({}); + if (b is WidgetStateBorderSide) { + b = b.resolve(const {}); } - if (b is MaterialStateBorderSide) { - b = b.resolve({}); - } - return BorderSide.lerp(a!, b!, t); + a ??= BorderSide(width: 0, color: b!.color.withAlpha(0)); + b ??= BorderSide(width: 0, color: a.color.withAlpha(0)); + + return BorderSide.lerp(a, b, t); } } diff --git a/packages/flutter/lib/src/material/chip_theme.dart b/packages/flutter/lib/src/material/chip_theme.dart index f2210e64f4c..8b582e60875 100644 --- a/packages/flutter/lib/src/material/chip_theme.dart +++ b/packages/flutter/lib/src/material/chip_theme.dart @@ -539,7 +539,7 @@ class ChipThemeData with Diagnosticable { labelPadding: EdgeInsetsGeometry.lerp(a?.labelPadding, b?.labelPadding, t), padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t), side: _lerpSides(a?.side, b?.side, t), - shape: _lerpShapes(a?.shape, b?.shape, t), + shape: OutlinedBorder.lerp(a?.shape, b?.shape, t), labelStyle: TextStyle.lerp(a?.labelStyle, b?.labelStyle, t), secondaryLabelStyle: TextStyle.lerp(a?.secondaryLabelStyle, b?.secondaryLabelStyle, t), brightness: t < 0.5 ? a?.brightness ?? Brightness.light : b?.brightness ?? Brightness.light, @@ -566,27 +566,16 @@ class ChipThemeData with Diagnosticable { if (a == null && b == null) { return null; } - if (a is MaterialStateBorderSide) { - a = a.resolve({}); + if (a is WidgetStateBorderSide) { + a = a.resolve(const {}); } - if (b is MaterialStateBorderSide) { - b = b.resolve({}); + if (b is WidgetStateBorderSide) { + b = b.resolve(const {}); } - if (a == null) { - return BorderSide.lerp(BorderSide(width: 0, color: b!.color.withAlpha(0)), b, t); - } - if (b == null) { - return BorderSide.lerp(BorderSide(width: 0, color: a.color.withAlpha(0)), a, t); - } - return BorderSide.lerp(a, b, t); - } + a ??= BorderSide(width: 0, color: b!.color.withAlpha(0)); + b ??= BorderSide(width: 0, color: a.color.withAlpha(0)); - // TODO(perclasson): OutlinedBorder needs a lerp method - https://github.com/flutter/flutter/issues/60555. - static OutlinedBorder? _lerpShapes(OutlinedBorder? a, OutlinedBorder? b, double t) { - if (a == null && b == null) { - return null; - } - return ShapeBorder.lerp(a, b, t) as OutlinedBorder?; + return BorderSide.lerp(a, b, t); } @override diff --git a/packages/flutter/lib/src/material/search_bar_theme.dart b/packages/flutter/lib/src/material/search_bar_theme.dart index 8a99804bee0..1e8b71716ae 100644 --- a/packages/flutter/lib/src/material/search_bar_theme.dart +++ b/packages/flutter/lib/src/material/search_bar_theme.dart @@ -155,7 +155,7 @@ class SearchBarThemeData with Diagnosticable { t, Color.lerp, ), - side: _lerpSides(a?.side, b?.side, t), + side: MaterialStateBorderSide.lerp(a?.side, b?.side, t), shape: MaterialStateProperty.lerp( a?.shape, b?.shape, @@ -304,18 +304,6 @@ class SearchBarThemeData with Diagnosticable { ), ); } - - // Special case because BorderSide.lerp() doesn't support null arguments - static MaterialStateProperty? _lerpSides( - MaterialStateProperty? a, - MaterialStateProperty? b, - double t, - ) { - if (identical(a, b)) { - return a; - } - return MaterialStateBorderSide.lerp(a, b, t); - } } /// Applies a search bar theme to descendant [SearchBar] widgets. diff --git a/packages/flutter/lib/src/material/search_view_theme.dart b/packages/flutter/lib/src/material/search_view_theme.dart index ee17846f080..980c4a02c9b 100644 --- a/packages/flutter/lib/src/material/search_view_theme.dart +++ b/packages/flutter/lib/src/material/search_view_theme.dart @@ -225,12 +225,18 @@ class SearchViewThemeData with Diagnosticable { // Special case because BorderSide.lerp() doesn't support null arguments static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) { - if (a == null || b == null) { + if (a == null && b == null) { return null; } - if (identical(a, b)) { - return a; + if (a is WidgetStateBorderSide) { + a = a.resolve(const {}); } + if (b is WidgetStateBorderSide) { + b = b.resolve(const {}); + } + a ??= BorderSide(width: 0, color: b!.color.withAlpha(0)); + b ??= BorderSide(width: 0, color: a.color.withAlpha(0)); + return BorderSide.lerp(a, b, t); } } diff --git a/packages/flutter/lib/src/widgets/widget_state.dart b/packages/flutter/lib/src/widgets/widget_state.dart index a80e2330b5d..b9f85d3b732 100644 --- a/packages/flutter/lib/src/widgets/widget_state.dart +++ b/packages/flutter/lib/src/widgets/widget_state.dart @@ -582,6 +582,9 @@ abstract class WidgetStateBorderSide extends BorderSide if (a == null && b == null) { return null; } + if (identical(a, b)) { + return a; + } return _LerpSides(a, b, t); } } diff --git a/packages/flutter/test/material/checkbox_theme_test.dart b/packages/flutter/test/material/checkbox_theme_test.dart index 685b44df6a3..775faf3fc35 100644 --- a/packages/flutter/test/material/checkbox_theme_test.dart +++ b/packages/flutter/test/material/checkbox_theme_test.dart @@ -458,8 +458,44 @@ void main() { lerped.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))), ); - // Returns null if either lerp value is null. - expect(lerped.side, null); + expect(lerped.side!.width, 2.0); + expect(lerped.side!.color, isSameColorAs(const Color(0x80000000))); + }); + + test('CheckboxThemeData lerp from null to populated parameters', () { + final CheckboxThemeData theme = CheckboxThemeData( + fillColor: MaterialStateProperty.all(const Color(0xfffffff0)), + checkColor: MaterialStateProperty.all(const Color(0xfffffff1)), + overlayColor: MaterialStateProperty.all(const Color(0xfffffff2)), + splashRadius: 4.0, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: const VisualDensity(vertical: 1.0, horizontal: 1.0), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))), + side: const BorderSide(width: 4.0), + ); + final CheckboxThemeData lerped = CheckboxThemeData.lerp(null, theme, 0.25); + + expect( + lerped.fillColor!.resolve(const {}), + isSameColorAs(const Color(0x40fffff0)), + ); + expect( + lerped.checkColor!.resolve(const {}), + isSameColorAs(const Color(0x40fffff1)), + ); + expect( + lerped.overlayColor!.resolve(const {}), + isSameColorAs(const Color(0x40fffff2)), + ); + expect(lerped.splashRadius, 1); + expect(lerped.materialTapTargetSize, null); + expect(lerped.visualDensity, null); + expect( + lerped.shape, + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(1.0))), + ); + expect(lerped.side!.width, 1.0); + expect(lerped.side!.color, isSameColorAs(const Color(0x40000000))); }); test('CheckboxThemeData lerp from populated parameters', () { diff --git a/packages/flutter/test/material/chip_theme_test.dart b/packages/flutter/test/material/chip_theme_test.dart index 6dafcefe774..aa540200735 100644 --- a/packages/flutter/test/material/chip_theme_test.dart +++ b/packages/flutter/test/material/chip_theme_test.dart @@ -738,7 +738,7 @@ void main() { expect(lerpBNull25.showCheckmark, equals(false)); expect(lerpBNull25.labelPadding, equals(const EdgeInsets.only(left: 6.0, right: 6.0))); expect(lerpBNull25.padding, equals(const EdgeInsets.all(3.0))); - expect(lerpBNull25.side!.color, isSameColorAs(Colors.black.withAlpha(0x3f))); + expect(lerpBNull25.side!.color, isSameColorAs(Colors.black.withAlpha(0xbf))); expect(lerpBNull25.shape, isA()); expect(lerpBNull25.labelStyle?.color, isSameColorAs(Colors.white.withAlpha(0xa7))); expect(lerpBNull25.secondaryLabelStyle?.color, isSameColorAs(Colors.black.withAlpha(0xa7))); @@ -760,7 +760,7 @@ void main() { expect(lerpBNull75.showCheckmark, equals(true)); expect(lerpBNull75.labelPadding, equals(const EdgeInsets.only(left: 2.0, right: 2.0))); expect(lerpBNull75.padding, equals(const EdgeInsets.all(1.0))); - expect(lerpBNull75.side!.color, isSameColorAs(Colors.black.withAlpha(0xbf))); + expect(lerpBNull75.side!.color, isSameColorAs(Colors.black.withAlpha(0x3f))); expect(lerpBNull75.shape, isA()); expect(lerpBNull75.labelStyle?.color, isSameColorAs(Colors.white.withAlpha(0x38))); expect(lerpBNull75.secondaryLabelStyle?.color, isSameColorAs(Colors.black.withAlpha(0x38)));