Unverified Commit 87804363 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Refactor `MaterialStateProperty` lerp functions (#104507)

parent 208a418a
...@@ -465,7 +465,7 @@ class ButtonStyle with Diagnosticable { ...@@ -465,7 +465,7 @@ class ButtonStyle with Diagnosticable {
fixedSize: _lerpProperties<Size?>(a?.fixedSize, b?.fixedSize, t, Size.lerp), fixedSize: _lerpProperties<Size?>(a?.fixedSize, b?.fixedSize, t, Size.lerp),
maximumSize: _lerpProperties<Size?>(a?.maximumSize, b?.maximumSize, t, Size.lerp), maximumSize: _lerpProperties<Size?>(a?.maximumSize, b?.maximumSize, t, Size.lerp),
side: _lerpSides(a?.side, b?.side, t), side: _lerpSides(a?.side, b?.side, t),
shape: _lerpShapes(a?.shape, b?.shape, t), shape: MaterialStateProperty.lerp<OutlinedBorder?>(a?.shape, b?.shape, t, OutlinedBorder.lerp),
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity, visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
tapTargetSize: t < 0.5 ? a?.tapTargetSize : b?.tapTargetSize, tapTargetSize: t < 0.5 ? a?.tapTargetSize : b?.tapTargetSize,
...@@ -491,14 +491,6 @@ class ButtonStyle with Diagnosticable { ...@@ -491,14 +491,6 @@ class ButtonStyle with Diagnosticable {
} }
return _LerpSides(a, b, t); return _LerpSides(a, b, t);
} }
// TODO(hansmuller): OutlinedBorder needs a lerp method - https://github.com/flutter/flutter/issues/60555.
static MaterialStateProperty<OutlinedBorder?>? _lerpShapes(MaterialStateProperty<OutlinedBorder?>? a, MaterialStateProperty<OutlinedBorder?>? b, double t) {
if (a == null && b == null) {
return null;
}
return _LerpShapes(a, b, t);
}
} }
class _LerpProperties<T> implements MaterialStateProperty<T?> { class _LerpProperties<T> implements MaterialStateProperty<T?> {
...@@ -540,18 +532,3 @@ class _LerpSides implements MaterialStateProperty<BorderSide?> { ...@@ -540,18 +532,3 @@ class _LerpSides implements MaterialStateProperty<BorderSide?> {
return BorderSide.lerp(resolvedA, resolvedB, t); return BorderSide.lerp(resolvedA, resolvedB, t);
} }
} }
class _LerpShapes implements MaterialStateProperty<OutlinedBorder?> {
const _LerpShapes(this.a, this.b, this.t);
final MaterialStateProperty<OutlinedBorder?>? a;
final MaterialStateProperty<OutlinedBorder?>? b;
final double t;
@override
OutlinedBorder? resolve(Set<MaterialState> states) {
final OutlinedBorder? resolvedA = a?.resolve(states);
final OutlinedBorder? resolvedB = b?.resolve(states);
return ShapeBorder.lerp(resolvedA, resolvedB, t) as OutlinedBorder?;
}
}
...@@ -129,9 +129,9 @@ class CheckboxThemeData with Diagnosticable { ...@@ -129,9 +129,9 @@ class CheckboxThemeData with Diagnosticable {
static CheckboxThemeData lerp(CheckboxThemeData? a, CheckboxThemeData? b, double t) { static CheckboxThemeData lerp(CheckboxThemeData? a, CheckboxThemeData? b, double t) {
return CheckboxThemeData( return CheckboxThemeData(
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
fillColor: _lerpProperties<Color?>(a?.fillColor, b?.fillColor, t, Color.lerp), fillColor: MaterialStateProperty.lerp<Color?>(a?.fillColor, b?.fillColor, t, Color.lerp),
checkColor: _lerpProperties<Color?>(a?.checkColor, b?.checkColor, t, Color.lerp), checkColor: MaterialStateProperty.lerp<Color?>(a?.checkColor, b?.checkColor, t, Color.lerp),
overlayColor: _lerpProperties<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp), overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
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,
...@@ -187,19 +187,6 @@ class CheckboxThemeData with Diagnosticable { ...@@ -187,19 +187,6 @@ class CheckboxThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<BorderSide>('side', side, defaultValue: null)); properties.add(DiagnosticsProperty<BorderSide>('side', side, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
// Special case because BorderSide.lerp() doesn't support null arguments // Special case because BorderSide.lerp() doesn't support null arguments
static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) { static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) {
if (a == null && b == null) { if (a == null && b == null) {
...@@ -209,22 +196,6 @@ class CheckboxThemeData with Diagnosticable { ...@@ -209,22 +196,6 @@ class CheckboxThemeData with Diagnosticable {
} }
} }
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
}
/// Applies a checkbox theme to descendant [Checkbox] widgets. /// Applies a checkbox theme to descendant [Checkbox] widgets.
/// ///
/// Descendant widgets obtain the current theme's [CheckboxTheme] object using /// Descendant widgets obtain the current theme's [CheckboxTheme] object using
......
...@@ -122,10 +122,10 @@ class DataTableThemeData with Diagnosticable { ...@@ -122,10 +122,10 @@ class DataTableThemeData with Diagnosticable {
assert(t != null); assert(t != null);
return DataTableThemeData( return DataTableThemeData(
decoration: Decoration.lerp(a.decoration, b.decoration, t), decoration: Decoration.lerp(a.decoration, b.decoration, t),
dataRowColor: _lerpProperties<Color?>(a.dataRowColor, b.dataRowColor, t, Color.lerp), dataRowColor: MaterialStateProperty.lerp<Color?>(a.dataRowColor, b.dataRowColor, t, Color.lerp),
dataRowHeight: lerpDouble(a.dataRowHeight, b.dataRowHeight, t), dataRowHeight: lerpDouble(a.dataRowHeight, b.dataRowHeight, t),
dataTextStyle: TextStyle.lerp(a.dataTextStyle, b.dataTextStyle, t), dataTextStyle: TextStyle.lerp(a.dataTextStyle, b.dataTextStyle, t),
headingRowColor: _lerpProperties<Color?>(a.headingRowColor, b.headingRowColor, t, Color.lerp), headingRowColor: MaterialStateProperty.lerp<Color?>(a.headingRowColor, b.headingRowColor, t, Color.lerp),
headingRowHeight: lerpDouble(a.headingRowHeight, b.headingRowHeight, t), headingRowHeight: lerpDouble(a.headingRowHeight, b.headingRowHeight, t),
headingTextStyle: TextStyle.lerp(a.headingTextStyle, b.headingTextStyle, t), headingTextStyle: TextStyle.lerp(a.headingTextStyle, b.headingTextStyle, t),
horizontalMargin: lerpDouble(a.horizontalMargin, b.horizontalMargin, t), horizontalMargin: lerpDouble(a.horizontalMargin, b.horizontalMargin, t),
...@@ -187,30 +187,6 @@ class DataTableThemeData with Diagnosticable { ...@@ -187,30 +187,6 @@ class DataTableThemeData with Diagnosticable {
properties.add(DoubleProperty('dividerThickness', dividerThickness, defaultValue: null)); properties.add(DoubleProperty('dividerThickness', dividerThickness, defaultValue: null));
properties.add(DoubleProperty('checkboxHorizontalMargin', checkboxHorizontalMargin, defaultValue: null)); properties.add(DoubleProperty('checkboxHorizontalMargin', checkboxHorizontalMargin, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(MaterialStateProperty<T>? a, MaterialStateProperty<T>? b, double t, T Function(T?, T?, double) lerpFunction ) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
/// Applies a data table theme to descendant [DataTable] widgets. /// Applies a data table theme to descendant [DataTable] widgets.
......
...@@ -658,6 +658,36 @@ abstract class MaterialStateProperty<T> { ...@@ -658,6 +658,36 @@ abstract class MaterialStateProperty<T> {
// a dart fix that will replace this with MaterialStatePropertyAll: // a dart fix that will replace this with MaterialStatePropertyAll:
// https://github.com/dart-lang/sdk/issues/49056. // https://github.com/dart-lang/sdk/issues/49056.
static MaterialStateProperty<T> all<T>(T value) => MaterialStatePropertyAll<T>(value); static MaterialStateProperty<T> all<T>(T value) => MaterialStatePropertyAll<T>(value);
/// Linearly interpolate between two [MaterialStateProperty]s.
static MaterialStateProperty<T?>? lerp<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T? Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T?> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T? Function(T?, T?, double) lerpFunction;
@override
T? resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
class _MaterialStatePropertyWith<T> implements MaterialStateProperty<T> { class _MaterialStatePropertyWith<T> implements MaterialStateProperty<T> {
......
...@@ -127,8 +127,8 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -127,8 +127,8 @@ class NavigationBarThemeData with Diagnosticable {
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t), indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t),
indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t), indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t),
labelTextStyle: _lerpProperties<TextStyle?>(a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp), labelTextStyle: MaterialStateProperty.lerp<TextStyle?>(a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp),
iconTheme: _lerpProperties<IconThemeData?>(a?.iconTheme, b?.iconTheme, t, IconThemeData.lerp), iconTheme: MaterialStateProperty.lerp<IconThemeData?>(a?.iconTheme, b?.iconTheme, t, IconThemeData.lerp),
labelBehavior: t < 0.5 ? a?.labelBehavior : b?.labelBehavior, labelBehavior: t < 0.5 ? a?.labelBehavior : b?.labelBehavior,
); );
} }
...@@ -179,35 +179,6 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -179,35 +179,6 @@ class NavigationBarThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<MaterialStateProperty<IconThemeData?>>('iconTheme', iconTheme, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<IconThemeData?>>('iconTheme', iconTheme, defaultValue: null));
properties.add(DiagnosticsProperty<NavigationDestinationLabelBehavior>('labelBehavior', labelBehavior, defaultValue: null)); properties.add(DiagnosticsProperty<NavigationDestinationLabelBehavior>('labelBehavior', labelBehavior, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
/// An inherited widget that defines visual properties for [NavigationBar]s and /// An inherited widget that defines visual properties for [NavigationBar]s and
......
...@@ -111,9 +111,9 @@ class RadioThemeData with Diagnosticable { ...@@ -111,9 +111,9 @@ class RadioThemeData with Diagnosticable {
static RadioThemeData lerp(RadioThemeData? a, RadioThemeData? b, double t) { static RadioThemeData lerp(RadioThemeData? a, RadioThemeData? b, double t) {
return RadioThemeData( return RadioThemeData(
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
fillColor: _lerpProperties<Color?>(a?.fillColor, b?.fillColor, t, Color.lerp), fillColor: MaterialStateProperty.lerp<Color?>(a?.fillColor, b?.fillColor, t, Color.lerp),
materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize, materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize,
overlayColor: _lerpProperties<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp), overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t), splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity, visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity,
); );
...@@ -156,35 +156,6 @@ class RadioThemeData with Diagnosticable { ...@@ -156,35 +156,6 @@ class RadioThemeData with Diagnosticable {
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));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
/// Applies a radio theme to descendant [Radio] widgets. /// Applies a radio theme to descendant [Radio] widgets.
......
...@@ -198,16 +198,16 @@ class ScrollbarThemeData with Diagnosticable { ...@@ -198,16 +198,16 @@ class ScrollbarThemeData with Diagnosticable {
static ScrollbarThemeData lerp(ScrollbarThemeData? a, ScrollbarThemeData? b, double t) { static ScrollbarThemeData lerp(ScrollbarThemeData? a, ScrollbarThemeData? b, double t) {
assert(t != null); assert(t != null);
return ScrollbarThemeData( return ScrollbarThemeData(
thumbVisibility: _lerpProperties<bool?>(a?.thumbVisibility, b?.thumbVisibility, t, _lerpBool), thumbVisibility: MaterialStateProperty.lerp<bool?>(a?.thumbVisibility, b?.thumbVisibility, t, _lerpBool),
thickness: _lerpProperties<double?>(a?.thickness, b?.thickness, t, lerpDouble), thickness: MaterialStateProperty.lerp<double?>(a?.thickness, b?.thickness, t, lerpDouble),
trackVisibility: _lerpProperties<bool?>(a?.trackVisibility, b?.trackVisibility, t, _lerpBool), trackVisibility: MaterialStateProperty.lerp<bool?>(a?.trackVisibility, b?.trackVisibility, t, _lerpBool),
showTrackOnHover: _lerpBool(a?.showTrackOnHover, b?.showTrackOnHover, t), showTrackOnHover: _lerpBool(a?.showTrackOnHover, b?.showTrackOnHover, t),
isAlwaysShown: _lerpBool(a?.isAlwaysShown, b?.isAlwaysShown, t), isAlwaysShown: _lerpBool(a?.isAlwaysShown, b?.isAlwaysShown, t),
interactive: _lerpBool(a?.interactive, b?.interactive, t), interactive: _lerpBool(a?.interactive, b?.interactive, t),
radius: Radius.lerp(a?.radius, b?.radius, t), radius: Radius.lerp(a?.radius, b?.radius, t),
thumbColor: _lerpProperties<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp), thumbColor: MaterialStateProperty.lerp<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp),
trackColor: _lerpProperties<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp), trackColor: MaterialStateProperty.lerp<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp),
trackBorderColor: _lerpProperties<Color?>(a?.trackBorderColor, b?.trackBorderColor, t, Color.lerp), trackBorderColor: MaterialStateProperty.lerp<Color?>(a?.trackBorderColor, b?.trackBorderColor, t, Color.lerp),
crossAxisMargin: lerpDouble(a?.crossAxisMargin, b?.crossAxisMargin, t), crossAxisMargin: lerpDouble(a?.crossAxisMargin, b?.crossAxisMargin, t),
mainAxisMargin: lerpDouble(a?.mainAxisMargin, b?.mainAxisMargin, t), mainAxisMargin: lerpDouble(a?.mainAxisMargin, b?.mainAxisMargin, t),
minThumbLength: lerpDouble(a?.minThumbLength, b?.minThumbLength, t), minThumbLength: lerpDouble(a?.minThumbLength, b?.minThumbLength, t),
...@@ -272,35 +272,6 @@ class ScrollbarThemeData with Diagnosticable { ...@@ -272,35 +272,6 @@ class ScrollbarThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<double>('mainAxisMargin', mainAxisMargin, defaultValue: null)); properties.add(DiagnosticsProperty<double>('mainAxisMargin', mainAxisMargin, defaultValue: null));
properties.add(DiagnosticsProperty<double>('minThumbLength', minThumbLength, defaultValue: null)); properties.add(DiagnosticsProperty<double>('minThumbLength', minThumbLength, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
bool? _lerpBool(bool? a, bool? b, double t) => t < 0.5 ? a : b; bool? _lerpBool(bool? a, bool? b, double t) => t < 0.5 ? a : b;
......
...@@ -98,11 +98,11 @@ class SwitchThemeData with Diagnosticable { ...@@ -98,11 +98,11 @@ class SwitchThemeData with Diagnosticable {
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static SwitchThemeData lerp(SwitchThemeData? a, SwitchThemeData? b, double t) { static SwitchThemeData lerp(SwitchThemeData? a, SwitchThemeData? b, double t) {
return SwitchThemeData( return SwitchThemeData(
thumbColor: _lerpProperties<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp), thumbColor: MaterialStateProperty.lerp<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp),
trackColor: _lerpProperties<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp), trackColor: MaterialStateProperty.lerp<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp),
materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize, materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize,
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
overlayColor: _lerpProperties<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp), overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t), splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
); );
} }
...@@ -144,35 +144,6 @@ class SwitchThemeData with Diagnosticable { ...@@ -144,35 +144,6 @@ class SwitchThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null)); properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
} }
static MaterialStateProperty<T>? _lerpProperties<T>(
MaterialStateProperty<T>? a,
MaterialStateProperty<T>? b,
double t,
T Function(T?, T?, double) lerpFunction,
) {
// Avoid creating a _LerpProperties object for a common case.
if (a == null && b == null) {
return null;
}
return _LerpProperties<T>(a, b, t, lerpFunction);
}
}
class _LerpProperties<T> implements MaterialStateProperty<T> {
const _LerpProperties(this.a, this.b, this.t, this.lerpFunction);
final MaterialStateProperty<T>? a;
final MaterialStateProperty<T>? b;
final double t;
final T Function(T?, T?, double) lerpFunction;
@override
T resolve(Set<MaterialState> states) {
final T? resolvedA = a?.resolve(states);
final T? resolvedB = b?.resolve(states);
return lerpFunction(resolvedA, resolvedB, t);
}
} }
/// Applies a switch theme to descendant [Switch] widgets. /// Applies a switch theme to descendant [Switch] widgets.
......
...@@ -566,6 +566,45 @@ abstract class OutlinedBorder extends ShapeBorder { ...@@ -566,6 +566,45 @@ abstract class OutlinedBorder extends ShapeBorder {
/// Returns a copy of this OutlinedBorder that draws its outline with the /// Returns a copy of this OutlinedBorder that draws its outline with the
/// specified [side], if [side] is non-null. /// specified [side], if [side] is non-null.
OutlinedBorder copyWith({ BorderSide? side }); OutlinedBorder copyWith({ BorderSide? side });
@override
ShapeBorder scale(double t);
@override
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a == null) {
return scale(t);
}
return null;
}
@override
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b == null) {
return scale(1.0 - t);
}
return null;
}
/// Linearly interpolates between two [OutlinedBorder]s.
///
/// This defers to `b`'s [lerpTo] function if `b` is not null. If `b` is
/// null or if its [lerpTo] returns null, it uses `a`'s [lerpFrom]
/// function instead. If both return null, it returns `a` before `t=0.5`
/// and `b` after `t=0.5`.
///
/// {@macro dart.ui.shadow.lerp}
static OutlinedBorder? lerp(OutlinedBorder? a, OutlinedBorder? b, double t) {
assert(t != null);
ShapeBorder? result;
if (b != null) {
result = b.lerpFrom(a, t);
}
if (result == null && a != null) {
result = a.lerpTo(b, t);
}
return result as OutlinedBorder? ?? (t < 0.5 ? a : b);
}
} }
/// Represents the addition of two otherwise-incompatible borders. /// Represents the addition of two otherwise-incompatible borders.
......
...@@ -42,4 +42,42 @@ void main() { ...@@ -42,4 +42,42 @@ void main() {
expect(value.resolve(<MaterialState>{MaterialState.disabled}), 123); expect(value.resolve(<MaterialState>{MaterialState.disabled}), 123);
expect(value.resolve(<MaterialState>{MaterialState.error}), 123); expect(value.resolve(<MaterialState>{MaterialState.error}), 123);
}); });
test("Can interpolate between two MaterialStateProperty's", () {
const MaterialStateProperty<TextStyle?> textStyle1 = MaterialStatePropertyAll<TextStyle?>(
TextStyle(fontSize: 14.0),
);
const MaterialStateProperty<TextStyle?> textStyle2 = MaterialStatePropertyAll<TextStyle?>(
TextStyle(fontSize: 20.0),
);
// Using `0.0` interpolation value.
TextStyle textStyle = MaterialStateProperty.lerp<TextStyle?>(
textStyle1,
textStyle2,
0.0,
TextStyle.lerp,
)!.resolve(enabled)!;
expect(textStyle.fontSize, 14.0);
// Using `0.5` interpolation value.
textStyle = MaterialStateProperty.lerp<TextStyle?>(
textStyle1,
textStyle2,
0.5,
TextStyle.lerp,
)!.resolve(enabled)!;
expect(textStyle.fontSize, 17.0);
// Using `1.0` interpolation value.
textStyle = MaterialStateProperty.lerp<TextStyle?>(
textStyle1,
textStyle2,
1.0,
TextStyle.lerp,
)!.resolve(enabled)!;
expect(textStyle.fontSize, 20.0);
});
} }
Set<MaterialState> enabled = <MaterialState>{};
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