Unverified Commit 0545c63b authored by MH Johnson's avatar MH Johnson Committed by GitHub

Revert "[Material] Update slider and slider theme with new sizes, shapes, and...

Revert "[Material] Update slider and slider theme with new sizes, shapes, and color mappings (#30390)" (#31339)

This reverts commit b1039f0f.

(This is a temporary revert while some of our customers deal with the breaking changes involved.)
parent 484f6e75
...@@ -428,52 +428,27 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin { ...@@ -428,52 +428,27 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
return widget.max > widget.min ? (value - widget.min) / (widget.max - widget.min) : 0.0; return widget.max > widget.min ? (value - widget.min) / (widget.max - widget.min) : 0.0;
} }
static const double _defaultTrackHeight = 2;
static const SliderTrackShape _defaultTrackShape = RoundedRectSliderTrackShape();
static const SliderTickMarkShape _defaultTickMarkShape = RoundSliderTickMarkShape();
static const SliderComponentShape _defaultOverlayShape = RoundSliderOverlayShape();
static const SliderComponentShape _defaultThumbShape = RoundSliderThumbShape();
static const SliderComponentShape _defaultValueIndicatorShape = PaddleSliderValueIndicatorShape();
static const ShowValueIndicator _defaultShowValueIndicator = ShowValueIndicator.onlyForDiscrete;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
assert(debugCheckHasMediaQuery(context)); assert(debugCheckHasMediaQuery(context));
final ThemeData theme = Theme.of(context);
SliderThemeData sliderTheme = SliderTheme.of(context); SliderThemeData sliderTheme = SliderTheme.of(context);
// If the widget has active or inactive colors specified, then we plug them // If the widget has active or inactive colors specified, then we plug them
// in to the slider theme as best we can. If the developer wants more // in to the slider theme as best we can. If the developer wants more
// control than that, then they need to use a SliderTheme. The default // control than that, then they need to use a SliderTheme.
// colors come from the ThemeData.colorScheme. These colors, along with if (widget.activeColor != null || widget.inactiveColor != null) {
// the default shapes and text styles are aligned to the Material sliderTheme = sliderTheme.copyWith(
// Guidelines. activeTrackColor: widget.activeColor,
sliderTheme = sliderTheme.copyWith( inactiveTrackColor: widget.inactiveColor,
trackHeight: sliderTheme.trackHeight ?? _defaultTrackHeight, activeTickMarkColor: widget.inactiveColor,
activeTrackColor: widget.activeColor ?? sliderTheme.activeTrackColor ?? theme.colorScheme.primary, inactiveTickMarkColor: widget.activeColor,
inactiveTrackColor: widget.inactiveColor ?? sliderTheme.inactiveTrackColor ?? theme.colorScheme.primary.withOpacity(0.24), thumbColor: widget.activeColor,
disabledActiveTrackColor: sliderTheme.disabledActiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.32), valueIndicatorColor: widget.activeColor,
disabledInactiveTrackColor: sliderTheme.disabledInactiveTrackColor ?? theme.colorScheme.onSurface.withOpacity(0.12), overlayColor: widget.activeColor?.withAlpha(0x29),
activeTickMarkColor: widget.inactiveColor ?? sliderTheme.activeTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.54), );
inactiveTickMarkColor: widget.activeColor ?? sliderTheme.inactiveTickMarkColor ?? theme.colorScheme.primary.withOpacity(0.54), }
disabledActiveTickMarkColor: sliderTheme.disabledActiveTickMarkColor ?? theme.colorScheme.onPrimary.withOpacity(0.12),
disabledInactiveTickMarkColor: sliderTheme.disabledInactiveTickMarkColor ?? theme.colorScheme.onSurface.withOpacity(0.12),
thumbColor: widget.activeColor ?? sliderTheme.thumbColor ?? theme.colorScheme.primary,
disabledThumbColor: sliderTheme.disabledThumbColor ?? theme.colorScheme.onSurface.withOpacity(0.38),
overlayColor: widget.activeColor?.withOpacity(0.12) ?? sliderTheme.overlayColor ?? theme.colorScheme.primary.withOpacity(0.12),
valueIndicatorColor: widget.activeColor ?? sliderTheme.valueIndicatorColor ?? theme.colorScheme.primary,
trackShape: sliderTheme.trackShape ?? _defaultTrackShape,
tickMarkShape: sliderTheme.tickMarkShape ?? _defaultTickMarkShape,
thumbShape: sliderTheme.thumbShape ?? _defaultThumbShape,
overlayShape: sliderTheme.overlayShape ?? _defaultOverlayShape,
valueIndicatorShape: sliderTheme.valueIndicatorShape ?? _defaultValueIndicatorShape,
showValueIndicator: sliderTheme.showValueIndicator ?? _defaultShowValueIndicator,
valueIndicatorTextStyle: sliderTheme.valueIndicatorTextStyle ?? theme.textTheme.body2.copyWith(
color: theme.colorScheme.onPrimary,
),
);
return _SliderRenderObjectWidget( return _SliderRenderObjectWidget(
value: _unlerp(widget.value), value: _unlerp(widget.value),
...@@ -523,6 +498,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -523,6 +498,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
divisions: divisions, divisions: divisions,
label: label, label: label,
sliderTheme: sliderTheme, sliderTheme: sliderTheme,
theme: Theme.of(context),
mediaQueryData: mediaQueryData, mediaQueryData: mediaQueryData,
onChanged: onChanged, onChanged: onChanged,
onChangeStart: onChangeStart, onChangeStart: onChangeStart,
...@@ -560,6 +536,7 @@ class _RenderSlider extends RenderBox { ...@@ -560,6 +536,7 @@ class _RenderSlider extends RenderBox {
int divisions, int divisions,
String label, String label,
SliderThemeData sliderTheme, SliderThemeData sliderTheme,
ThemeData theme,
MediaQueryData mediaQueryData, MediaQueryData mediaQueryData,
TargetPlatform platform, TargetPlatform platform,
ValueChanged<double> onChanged, ValueChanged<double> onChanged,
...@@ -577,6 +554,7 @@ class _RenderSlider extends RenderBox { ...@@ -577,6 +554,7 @@ class _RenderSlider extends RenderBox {
_value = value, _value = value,
_divisions = divisions, _divisions = divisions,
_sliderTheme = sliderTheme, _sliderTheme = sliderTheme,
_theme = theme,
_mediaQueryData = mediaQueryData, _mediaQueryData = mediaQueryData,
_onChanged = onChanged, _onChanged = onChanged,
_state = state, _state = state,
...@@ -1005,6 +983,7 @@ class _RenderSlider extends RenderBox { ...@@ -1005,6 +983,7 @@ class _RenderSlider extends RenderBox {
isEnabled: isInteractive, isEnabled: isInteractive,
); );
// TODO(closkmith): Move this to paint after the thumb.
if (!_overlayAnimation.isDismissed) { if (!_overlayAnimation.isDismissed) {
_sliderTheme.overlayShape.paint( _sliderTheme.overlayShape.paint(
context, context,
...@@ -1021,6 +1000,7 @@ class _RenderSlider extends RenderBox { ...@@ -1021,6 +1000,7 @@ class _RenderSlider extends RenderBox {
} }
if (isDiscrete) { if (isDiscrete) {
// TODO(clocksmith): Align tick mark centers to ends of track by not subtracting diameter from length.
final double tickMarkWidth = _sliderTheme.tickMarkShape.getPreferredSize( final double tickMarkWidth = _sliderTheme.tickMarkShape.getPreferredSize(
isEnabled: isInteractive, isEnabled: isInteractive,
sliderTheme: _sliderTheme, sliderTheme: _sliderTheme,
......
...@@ -210,27 +210,46 @@ class SliderThemeData extends Diagnosticable { ...@@ -210,27 +210,46 @@ class SliderThemeData extends Diagnosticable {
/// ``` /// ```
/// {@end-tool} /// {@end-tool}
const SliderThemeData({ const SliderThemeData({
this.trackHeight, @required this.trackHeight,
this.activeTrackColor, @required this.activeTrackColor,
this.inactiveTrackColor, @required this.inactiveTrackColor,
this.disabledActiveTrackColor, @required this.disabledActiveTrackColor,
this.disabledInactiveTrackColor, @required this.disabledInactiveTrackColor,
this.activeTickMarkColor, @required this.activeTickMarkColor,
this.inactiveTickMarkColor, @required this.inactiveTickMarkColor,
this.disabledActiveTickMarkColor, @required this.disabledActiveTickMarkColor,
this.disabledInactiveTickMarkColor, @required this.disabledInactiveTickMarkColor,
this.thumbColor, @required this.thumbColor,
this.disabledThumbColor, @required this.disabledThumbColor,
this.overlayColor, @required this.overlayColor,
this.valueIndicatorColor, @required this.valueIndicatorColor,
this.trackShape, @required this.trackShape,
this.tickMarkShape, @required this.tickMarkShape,
this.thumbShape, @required this.thumbShape,
this.overlayShape, @required this.overlayShape,
this.valueIndicatorShape, @required this.valueIndicatorShape,
this.showValueIndicator, @required this.showValueIndicator,
this.valueIndicatorTextStyle, @required this.valueIndicatorTextStyle,
}); }) : assert(trackHeight != null),
assert(activeTrackColor != null),
assert(inactiveTrackColor != null),
assert(disabledActiveTrackColor != null),
assert(disabledInactiveTrackColor != null),
assert(activeTickMarkColor != null),
assert(inactiveTickMarkColor != null),
assert(disabledActiveTickMarkColor != null),
assert(disabledInactiveTickMarkColor != null),
assert(thumbColor != null),
assert(disabledThumbColor != null),
assert(overlayColor != null),
assert(valueIndicatorColor != null),
assert(trackShape != null),
assert(tickMarkShape != null),
assert(thumbShape != null),
assert(overlayShape != null),
assert(valueIndicatorShape != null),
assert(valueIndicatorTextStyle != null),
assert(showValueIndicator != null);
/// Generates a SliderThemeData from three main colors. /// Generates a SliderThemeData from three main colors.
/// ///
...@@ -264,9 +283,15 @@ class SliderThemeData extends Diagnosticable { ...@@ -264,9 +283,15 @@ class SliderThemeData extends Diagnosticable {
const int disabledInactiveTickMarkAlpha = 0x1f; // 12% opacity const int disabledInactiveTickMarkAlpha = 0x1f; // 12% opacity
const int thumbAlpha = 0xff; const int thumbAlpha = 0xff;
const int disabledThumbAlpha = 0x52; // 32% opacity const int disabledThumbAlpha = 0x52; // 32% opacity
const int overlayAlpha = 0x1f; // 12% opacity
const int valueIndicatorAlpha = 0xff; const int valueIndicatorAlpha = 0xff;
// TODO(gspencer): We don't really follow the spec here for overlays.
// The spec says to use 16% opacity for drawing over light material,
// and 32% for colored material, but we don't really have a way to
// know what the underlying color is, so there's no easy way to
// implement this. Choosing the "light" version for now.
const int overlayLightAlpha = 0x29; // 16% opacity
return SliderThemeData( return SliderThemeData(
trackHeight: 2.0, trackHeight: 2.0,
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha), activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
...@@ -279,9 +304,9 @@ class SliderThemeData extends Diagnosticable { ...@@ -279,9 +304,9 @@ class SliderThemeData extends Diagnosticable {
disabledInactiveTickMarkColor: primaryColorDark.withAlpha(disabledInactiveTickMarkAlpha), disabledInactiveTickMarkColor: primaryColorDark.withAlpha(disabledInactiveTickMarkAlpha),
thumbColor: primaryColor.withAlpha(thumbAlpha), thumbColor: primaryColor.withAlpha(thumbAlpha),
disabledThumbColor: primaryColorDark.withAlpha(disabledThumbAlpha), disabledThumbColor: primaryColorDark.withAlpha(disabledThumbAlpha),
overlayColor: primaryColor.withAlpha(overlayAlpha), overlayColor: primaryColor.withAlpha(overlayLightAlpha),
valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha), valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha),
trackShape: const RoundedRectSliderTrackShape(), trackShape: const RectangularSliderTrackShape(),
tickMarkShape: const RoundSliderTickMarkShape(), tickMarkShape: const RoundSliderTickMarkShape(),
thumbShape: const RoundSliderThumbShape(), thumbShape: const RoundSliderThumbShape(),
overlayShape: const RoundSliderOverlayShape(), overlayShape: const RoundSliderOverlayShape(),
...@@ -902,151 +927,15 @@ class _EmptySliderComponentShape extends SliderComponentShape { ...@@ -902,151 +927,15 @@ class _EmptySliderComponentShape extends SliderComponentShape {
} }
} }
/// Base track shape that provides an implementation of [getPreferredRect] for // The following shapes are the material defaults.
/// default sizing.
///
/// See also:
///
/// * [RectangularSliderTrackShape], which is a track shape with sharp
/// rectangular edges
/// * [RoundedRectSliderTrackShape], which is a track shape with round
/// stadium-like edges.
///
/// The height is set from [SliderThemeData.trackHeight] and the width of the
/// parent box less the larger of the widths of [SliderThemeData.thumbShape] and
/// [SliderThemeData.overlayShape].
abstract class BaseSliderTrackShape {
/// Returns a rect that represents the track bounds that fits within the
/// [Slider].
///
/// The width is the width of the [Slider], but padded by the max
/// of the overlay and thumb radius. The height is defined by the
/// [SliderThemeData.trackHeight].
///
/// The [Rect] is centered both horizontally and vertically within the slider
/// bounds.
Rect getPreferredRect({
@required RenderBox parentBox,
Offset offset = Offset.zero,
SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
assert(parentBox != null);
final double thumbWidth = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete).width;
final double overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
final double trackHeight = sliderTheme.trackHeight;
assert(overlayWidth >= 0);
assert(trackHeight >= 0);
assert(parentBox.size.width >= overlayWidth);
assert(parentBox.size.height >= trackHeight);
final double trackLeft = offset.dx + overlayWidth / 2;
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
final double trackWidth = parentBox.size.width - math.max(thumbWidth, overlayWidth);
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}
/// This is the default shape of a [Slider]'s track. /// This is the default shape of a [Slider]'s track.
/// ///
/// It paints a solid colored rectangle with rounded edges, vertically centered
/// in the [parentBox]. The track rectangle extends to the bounds of the
/// [parentBox], but is padded by the larger of [RoundSliderOverlayShape]'s
/// radius and [RoundSliderThumbShape]'s radius. The height is defined by the
/// [SliderThemeData.trackHeight]. The color is determined by the [Slider]'s
/// enabled state and the track segment's active state which are defined by:
/// [SliderThemeData.activeTrackColor],
/// [SliderThemeData.inactiveTrackColor],
/// [SliderThemeData.disabledActiveTrackColor],
/// [SliderThemeData.disabledInactiveTrackColor].
///
/// See also:
///
/// * [Slider], for the component that is meant to display this shape.
/// * [SliderThemeData], where an instance of this class is set to inform the
/// slider of the visual details of the its track.
/// * [SliderTrackShape], which is the base component for creating other
/// custom track shapes.
/// * [RectangularSliderTrackShape], for a similar track with sharp edges.
class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackShape {
/// Create a slider track that draws two rectangles with rounded outer edges.
const RoundedRectSliderTrackShape();
@override
void paint(
PaintingContext context,
Offset offset, {
@required RenderBox parentBox,
@required SliderThemeData sliderTheme,
@required Animation<double> enableAnimation,
@required TextDirection textDirection,
@required Offset thumbCenter,
bool isDiscrete = false,
bool isEnabled = false,
}) {
assert(context != null);
assert(offset != null);
assert(parentBox != null);
assert(sliderTheme != null);
assert(enableAnimation != null);
assert(textDirection != null);
assert(thumbCenter != null);
// If the slider track height is less than or equal to 0, then it makes no
// difference whether the track is painted or not, therefore the painting
// can be a no-op.
if (sliderTheme.trackHeight <= 0) {
return;
}
// Assign the track segment paints, which are leading: active and
// trailing: inactive.
final ColorTween activeTrackColorTween = ColorTween(begin: sliderTheme.disabledActiveTrackColor, end: sliderTheme.activeTrackColor);
final ColorTween inactiveTrackColorTween = ColorTween(begin: sliderTheme.disabledInactiveTrackColor, end: sliderTheme.inactiveTrackColor);
final Paint activePaint = Paint()..color = activeTrackColorTween.evaluate(enableAnimation);
final Paint inactivePaint = Paint()..color = inactiveTrackColorTween.evaluate(enableAnimation);
Paint leftTrackPaint;
Paint rightTrackPaint;
switch (textDirection) {
case TextDirection.ltr:
leftTrackPaint = activePaint;
rightTrackPaint = inactivePaint;
break;
case TextDirection.rtl:
leftTrackPaint = inactivePaint;
rightTrackPaint = activePaint;
break;
}
final Rect trackRect = getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete,
);
// The arc rects create a semi-circle with radius equal to track height.
final Rect leftTrackArcRect = Rect.fromLTWH(trackRect.left, trackRect.top, trackRect.height, trackRect.height);
context.canvas.drawArc(leftTrackArcRect, math.pi / 2, math.pi, false, leftTrackPaint);
final Rect rightTrackArcRect = Rect.fromLTWH(trackRect.right - trackRect.height / 2, trackRect.top, trackRect.height, trackRect.height);
context.canvas.drawArc(rightTrackArcRect, -math.pi / 2, math.pi, false, rightTrackPaint);
final Size thumbSize = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete);
final Rect leftTrackSegment = Rect.fromLTRB(trackRect.left + trackRect.height / 2, trackRect.top, thumbCenter.dx - thumbSize.width / 2, trackRect.bottom);
context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
final Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + thumbSize.width / 2, trackRect.top, trackRect.right, trackRect.bottom);
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
}
}
/// A [Slider] track that's a simple rectangle.
///
/// It paints a solid colored rectangle, vertically centered in the /// It paints a solid colored rectangle, vertically centered in the
/// [parentBox]. The track rectangle extends to the bounds of the [parentBox], /// [parentBox]. The track rectangle extends to the bounds of the [parentBox],
/// but is padded by the [RoundSliderOverlayShape] radius. The height is defined /// but is padded by the [RoundSliderOverlayShape] radius. The height is defined
/// by the [SliderThemeData.trackHeight]. The color is determined by the /// by the [SliderThemeData.trackHeight]. The color is determined by the
/// [Slider]'s enabled state and the track segments's active state which are /// [Slider]'s enabled state and the track piece's active state which are
/// defined by: /// defined by:
/// [SliderThemeData.activeTrackColor], /// [SliderThemeData.activeTrackColor],
/// [SliderThemeData.inactiveTrackColor], /// [SliderThemeData.inactiveTrackColor],
...@@ -1055,12 +944,11 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS ...@@ -1055,12 +944,11 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
/// ///
/// See also: /// See also:
/// ///
/// * [Slider], for the component that is meant to display this shape. /// * [Slider] for the component that this is meant to display this shape.
/// * [SliderThemeData], where an instance of this class is set to inform the /// * [SliderThemeData] where an instance of this class is set to inform the
/// slider of the visual details of the its track. /// slider of the visual details of the its track.
/// * [SliderTrackShape], which is the base component for creating other /// * [SliderTrackShape] Base component for creating other custom track
/// custom track shapes. /// shapes.
/// * [RoundedRectSliderTrackShape], for a similar track with rounded edges.
class RectangularSliderTrackShape extends SliderTrackShape { class RectangularSliderTrackShape extends SliderTrackShape {
/// Create a slider track that draws 2 rectangles. /// Create a slider track that draws 2 rectangles.
const RectangularSliderTrackShape({ this.disabledThumbGapWidth = 2.0 }); const RectangularSliderTrackShape({ this.disabledThumbGapWidth = 2.0 });
...@@ -1075,15 +963,12 @@ class RectangularSliderTrackShape extends SliderTrackShape { ...@@ -1075,15 +963,12 @@ class RectangularSliderTrackShape extends SliderTrackShape {
@override @override
Rect getPreferredRect({ Rect getPreferredRect({
@required RenderBox parentBox, RenderBox parentBox,
Offset offset = Offset.zero, Offset offset = Offset.zero,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
bool isEnabled = false, bool isEnabled,
bool isDiscrete = false, bool isDiscrete,
}) { }) {
assert(parentBox != null);
assert(sliderTheme != null);
final double thumbWidth = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete).width;
final double overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width; final double overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
final double trackHeight = sliderTheme.trackHeight; final double trackHeight = sliderTheme.trackHeight;
assert(overlayWidth >= 0); assert(overlayWidth >= 0);
...@@ -1093,33 +978,29 @@ class RectangularSliderTrackShape extends SliderTrackShape { ...@@ -1093,33 +978,29 @@ class RectangularSliderTrackShape extends SliderTrackShape {
final double trackLeft = offset.dx + overlayWidth / 2; final double trackLeft = offset.dx + overlayWidth / 2;
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2; final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
final double trackWidth = parentBox.size.width - math.max(thumbWidth, overlayWidth); // TODO(clocksmith): Although this works for a material, perhaps the default
// rectangular track should be padded not just by the overlay, but by the
// max of the thumb and the overlay, in case there is no overlay.
final double trackWidth = parentBox.size.width - overlayWidth;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight); return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
} }
@override @override
void paint( void paint(
PaintingContext context, PaintingContext context,
Offset offset, { Offset offset, {
@required RenderBox parentBox, RenderBox parentBox,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
@required Animation<double> enableAnimation, Animation<double> enableAnimation,
@required TextDirection textDirection, TextDirection textDirection,
@required Offset thumbCenter, Offset thumbCenter,
bool isDiscrete = false, bool isDiscrete,
bool isEnabled = false, bool isEnabled,
}) { }) {
assert(context != null); // If the slider track height is 0, then it makes no difference whether the
assert(offset != null); // track is painted or not, therefore the painting can be a no-op.
assert(parentBox != null); if (sliderTheme.trackHeight == 0) {
assert(sliderTheme != null);
assert(enableAnimation != null);
assert(textDirection != null);
assert(thumbCenter != null);
// If the slider track height is less than or equal to 0, then it makes no
// difference whether the track is painted or not, therefore the painting
// can be a no-op.
if (sliderTheme.trackHeight <= 0) {
return; return;
} }
...@@ -1142,17 +1023,28 @@ class RectangularSliderTrackShape extends SliderTrackShape { ...@@ -1142,17 +1023,28 @@ class RectangularSliderTrackShape extends SliderTrackShape {
break; break;
} }
// Used to create a gap around the thumb iff the slider is disabled.
// If the slider is enabled, the track can be drawn beneath the thumb
// without a gap. But when the slider is disabled, the track is shortened
// and this gap helps determine how much shorter it should be.
// TODO(clocksmith): The new Material spec has a gray circle in place of this gap.
double horizontalAdjustment = 0.0;
if (!isEnabled) {
final double disabledThumbRadius = sliderTheme.thumbShape.getPreferredSize(false, isDiscrete).width / 2.0;
final double gap = disabledThumbGapWidth * (1.0 - enableAnimation.value);
horizontalAdjustment = disabledThumbRadius + gap;
}
final Rect trackRect = getPreferredRect( final Rect trackRect = getPreferredRect(
parentBox: parentBox, parentBox: parentBox,
offset: offset, offset: offset,
sliderTheme: sliderTheme, sliderTheme: sliderTheme,
isEnabled: isEnabled, isEnabled: isEnabled,
isDiscrete: isDiscrete, isDiscrete: isDiscrete,
); );
final Rect leftTrackSegment = Rect.fromLTRB(trackRect.left, trackRect.top, thumbCenter.dx - horizontalAdjustment, trackRect.bottom);
final Rect leftTrackSegment = Rect.fromLTRB(trackRect.left, trackRect.top, thumbCenter.dx, trackRect.bottom);
context.canvas.drawRect(leftTrackSegment, leftTrackPaint); context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
final Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx, trackRect.top, trackRect.right, trackRect.bottom); final Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + horizontalAdjustment, trackRect.top, trackRect.right, trackRect.bottom);
context.canvas.drawRect(rightTrackSegment, rightTrackPaint); context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
} }
} }
...@@ -1198,20 +1090,13 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape { ...@@ -1198,20 +1090,13 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape {
void paint( void paint(
PaintingContext context, PaintingContext context,
Offset center, { Offset center, {
@required RenderBox parentBox, RenderBox parentBox,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
@required Animation<double> enableAnimation, Animation<double> enableAnimation,
@required TextDirection textDirection, TextDirection textDirection,
@required Offset thumbCenter, Offset thumbCenter,
bool isEnabled = false, bool isEnabled,
}) { }) {
assert(context != null);
assert(center != null);
assert(parentBox != null);
assert(sliderTheme != null);
assert(enableAnimation != null);
assert(textDirection != null);
assert(thumbCenter != null);
// The paint color of the tick mark depends on its position relative // The paint color of the tick mark depends on its position relative
// to the thumb and the text direction. // to the thumb and the text direction.
Color begin; Color begin;
...@@ -1248,22 +1133,26 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape { ...@@ -1248,22 +1133,26 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape {
/// sliders in a widget subtree. /// sliders in a widget subtree.
class RoundSliderThumbShape extends SliderComponentShape { class RoundSliderThumbShape extends SliderComponentShape {
/// Create a slider thumb that draws a circle. /// Create a slider thumb that draws a circle.
// TODO(clocksmith): This needs to be changed to 10 according to spec.
const RoundSliderThumbShape({ const RoundSliderThumbShape({
this.enabledThumbRadius = 10.0, this.enabledThumbRadius = 6.0,
this.disabledThumbRadius, this.disabledThumbRadius,
}); });
/// The preferred radius of the round thumb shape when the slider is enabled. /// The preferred radius of the round thumb shape when the slider is enabled.
/// ///
/// If it is not provided, then the material default of 10 is used. /// If it is not provided, then the material default is used.
final double enabledThumbRadius; final double enabledThumbRadius;
/// The preferred radius of the round thumb shape when the slider is disabled. /// The preferred radius of the round thumb shape when the slider is disabled.
/// ///
/// If no disabledRadius is provided, then it is equal to the /// If no disabledRadius is provided, then it is is derived from the enabled
/// [enabledThumbRadius] /// thumb radius and has the same ratio of enabled size to disabled size as
/// the Material spec. The default resolves to 4, which is 2 / 3 of the
/// default enabled thumb.
final double disabledThumbRadius; final double disabledThumbRadius;
double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius; // TODO(clocksmith): This needs to be updated once the thumb size is updated to the Material spec.
double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius * 2 / 3;
@override @override
Size getPreferredSize(bool isEnabled, bool isDiscrete) { Size getPreferredSize(bool isEnabled, bool isDiscrete) {
...@@ -1274,24 +1163,15 @@ class RoundSliderThumbShape extends SliderComponentShape { ...@@ -1274,24 +1163,15 @@ class RoundSliderThumbShape extends SliderComponentShape {
void paint( void paint(
PaintingContext context, PaintingContext context,
Offset center, { Offset center, {
@required Animation<double> activationAnimation, Animation<double> activationAnimation,
@required Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete = false, bool isDiscrete,
@required TextPainter labelPainter, TextPainter labelPainter,
@required RenderBox parentBox, RenderBox parentBox,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
@required TextDirection textDirection, TextDirection textDirection,
@required double value, double value,
}) { }) {
assert(context != null);
assert(center != null);
assert(activationAnimation != null);
assert(enableAnimation != null);
assert(labelPainter != null);
assert(parentBox != null);
assert(sliderTheme != null);
assert(textDirection != null);
assert(value != null);
final Canvas canvas = context.canvas; final Canvas canvas = context.canvas;
final Tween<double> radiusTween = Tween<double>( final Tween<double> radiusTween = Tween<double>(
begin: _disabledThumbRadius, begin: _disabledThumbRadius,
...@@ -1326,7 +1206,8 @@ class RoundSliderThumbShape extends SliderComponentShape { ...@@ -1326,7 +1206,8 @@ class RoundSliderThumbShape extends SliderComponentShape {
/// sliders in a widget subtree. /// sliders in a widget subtree.
class RoundSliderOverlayShape extends SliderComponentShape { class RoundSliderOverlayShape extends SliderComponentShape {
/// Create a slider thumb overlay that draws a circle. /// Create a slider thumb overlay that draws a circle.
const RoundSliderOverlayShape({ this.overlayRadius = 24.0 }); // TODO(clocksmith): This needs to be changed to 24 according to spec.
const RoundSliderOverlayShape({ this.overlayRadius = 16.0 });
/// The preferred radius of the round thumb shape when enabled. /// The preferred radius of the round thumb shape when enabled.
/// ///
...@@ -1342,30 +1223,26 @@ class RoundSliderOverlayShape extends SliderComponentShape { ...@@ -1342,30 +1223,26 @@ class RoundSliderOverlayShape extends SliderComponentShape {
void paint( void paint(
PaintingContext context, PaintingContext context,
Offset center, { Offset center, {
@required Animation<double> activationAnimation, Animation<double> activationAnimation,
@required Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete = false, bool isDiscrete,
@required TextPainter labelPainter, TextPainter labelPainter,
@required RenderBox parentBox, RenderBox parentBox,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
@required TextDirection textDirection, TextDirection textDirection,
@required double value, double value,
}) { }) {
assert(context != null);
assert(center != null);
assert(activationAnimation != null);
assert(enableAnimation != null);
assert(labelPainter != null);
assert(parentBox != null);
assert(sliderTheme != null);
assert(textDirection != null);
assert(value != null);
final Canvas canvas = context.canvas; final Canvas canvas = context.canvas;
final Tween<double> radiusTween = Tween<double>( final Tween<double> radiusTween = Tween<double>(
begin: 0.0, begin: 0.0,
end: overlayRadius, end: overlayRadius,
); );
// TODO(gspencer): We don't really follow the spec here for overlays.
// The spec says to use 16% opacity for drawing over light material,
// and 32% for colored material, but we don't really have a way to
// know what the underlying color is, so there's no easy way to
// implement this. Choosing the "light" version for now.
canvas.drawCircle( canvas.drawCircle(
center, center,
radiusTween.evaluate(activationAnimation), radiusTween.evaluate(activationAnimation),
...@@ -1447,7 +1324,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -1447,7 +1324,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
final Path path = Path(); final Path path = Path();
final Offset bottomKnobStart = Offset( final Offset bottomKnobStart = Offset(
_bottomLobeRadius * math.cos(_bottomLobeStartAngle), _bottomLobeRadius * math.cos(_bottomLobeStartAngle),
_bottomLobeRadius * math.sin(_bottomLobeStartAngle) - 2, _bottomLobeRadius * math.sin(_bottomLobeStartAngle),
); );
final Offset bottomNeckRightCenter = bottomKnobStart + final Offset bottomNeckRightCenter = bottomKnobStart +
Offset( Offset(
...@@ -1597,7 +1474,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -1597,7 +1474,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
// The distance between the end of the bottom neck arc and the beginning of // The distance between the end of the bottom neck arc and the beginning of
// the top neck arc. We use this to shrink/expand it based on the scale // the top neck arc. We use this to shrink/expand it based on the scale
// factor of the value indicator. // factor of the value indicator.
final double neckStretchBaseline = math.max(0.0, bottomLobeEnd.dy - math.max(neckLeftCenter.dy, neckRightCenter.dy)); final double neckStretchBaseline = bottomLobeEnd.dy - math.max(neckLeftCenter.dy, neckRightCenter.dy);
final double t = math.pow(inverseTextScale, 3.0); final double t = math.pow(inverseTextScale, 3.0);
final double stretch = (neckStretchBaseline * t).clamp(0.0, 10.0 * neckStretchBaseline); final double stretch = (neckStretchBaseline * t).clamp(0.0, 10.0 * neckStretchBaseline);
final Offset neckStretch = Offset(0.0, neckStretchBaseline - stretch); final Offset neckStretch = Offset(0.0, neckStretchBaseline - stretch);
...@@ -1663,24 +1540,15 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -1663,24 +1540,15 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
void paint( void paint(
PaintingContext context, PaintingContext context,
Offset center, { Offset center, {
@required Animation<double> activationAnimation, Animation<double> activationAnimation,
@required Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete = false, bool isDiscrete,
@required TextPainter labelPainter, TextPainter labelPainter,
@required RenderBox parentBox, RenderBox parentBox,
@required SliderThemeData sliderTheme, SliderThemeData sliderTheme,
@required TextDirection textDirection, TextDirection textDirection,
@required double value, double value,
}) { }) {
assert(context != null);
assert(center != null);
assert(activationAnimation != null);
assert(enableAnimation != null);
assert(labelPainter != null);
assert(parentBox != null);
assert(sliderTheme != null);
assert(textDirection != null);
assert(value != null);
final ColorTween enableColor = ColorTween( final ColorTween enableColor = ColorTween(
begin: sliderTheme.disabledThumbColor, begin: sliderTheme.disabledThumbColor,
end: sliderTheme.valueIndicatorColor, end: sliderTheme.valueIndicatorColor,
......
...@@ -243,7 +243,12 @@ class ThemeData extends Diagnosticable { ...@@ -243,7 +243,12 @@ class ThemeData extends Diagnosticable {
highlightColor ??= isDark ? _kDarkThemeHighlightColor : _kLightThemeHighlightColor; highlightColor ??= isDark ? _kDarkThemeHighlightColor : _kLightThemeHighlightColor;
splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor; splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor;
sliderTheme ??= const SliderThemeData(); sliderTheme ??= SliderThemeData.fromPrimaryColors(
primaryColor: primaryColor,
primaryColorLight: primaryColorLight,
primaryColorDark: primaryColorDark,
valueIndicatorTextStyle: accentTextTheme.body2,
);
tabBarTheme ??= const TabBarTheme(); tabBarTheme ??= const TabBarTheme();
appBarTheme ??= const AppBarTheme(); appBarTheme ??= const AppBarTheme();
bottomAppBarTheme ??= const BottomAppBarTheme(); bottomAppBarTheme ??= const BottomAppBarTheme();
......
...@@ -298,8 +298,8 @@ void main() { ...@@ -298,8 +298,8 @@ void main() {
); );
final List<Offset> expectedLog = <Offset>[ final List<Offset> expectedLog = <Offset>[
const Offset(24.0, 300.0), const Offset(16.0, 300.0),
const Offset(24.0, 300.0), const Offset(16.0, 300.0),
const Offset(400.0, 300.0), const Offset(400.0, 300.0),
]; ];
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey))); final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
...@@ -313,20 +313,20 @@ void main() { ...@@ -313,20 +313,20 @@ void main() {
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 5); expect(log.length, 5);
expect(log.last.dx, closeTo(386.6, 0.1)); expect(log.last.dx, closeTo(386.3, 0.1));
// With no more gesture or value changes, the thumb position should still // With no more gesture or value changes, the thumb position should still
// be redrawn in the animated position. // be redrawn in the animated position.
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 7); expect(log.length, 7);
expect(log.last.dx, closeTo(344.5, 0.1)); expect(log.last.dx, closeTo(343.3, 0.1));
// Final position. // Final position.
await tester.pump(const Duration(milliseconds: 80)); await tester.pump(const Duration(milliseconds: 80));
expectedLog.add(const Offset(24.0, 300.0)); expectedLog.add(const Offset(16.0, 300.0));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 8); expect(log.length, 8);
expect(log.last.dx, closeTo(24.0, 0.1)); expect(log.last.dx, closeTo(16.0, 0.1));
await gesture.up(); await gesture.up();
}); });
...@@ -409,8 +409,8 @@ void main() { ...@@ -409,8 +409,8 @@ void main() {
); );
final List<Offset> expectedLog = <Offset>[ final List<Offset> expectedLog = <Offset>[
const Offset(24.0, 300.0), const Offset(16.0, 300.0),
const Offset(24.0, 300.0), const Offset(16.0, 300.0),
const Offset(400.0, 300.0), const Offset(400.0, 300.0),
]; ];
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey))); final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
...@@ -424,20 +424,20 @@ void main() { ...@@ -424,20 +424,20 @@ void main() {
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 5); expect(log.length, 5);
expect(log.last.dx, closeTo(386.6, 0.1)); expect(log.last.dx, closeTo(386.3, 0.1));
// With no more gesture or value changes, the thumb position should still // With no more gesture or value changes, the thumb position should still
// be redrawn in the animated position. // be redrawn in the animated position.
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 7); expect(log.length, 7);
expect(log.last.dx, closeTo(344.5, 0.1)); expect(log.last.dx, closeTo(343.3, 0.1));
// Final position. // Final position.
await tester.pump(const Duration(milliseconds: 80)); await tester.pump(const Duration(milliseconds: 80));
expectedLog.add(const Offset(24.0, 300.0)); expectedLog.add(const Offset(16.0, 300.0));
expect(value, equals(0.0)); expect(value, equals(0.0));
expect(log.length, 8); expect(log.length, 8);
expect(log.last.dx, closeTo(24.0, 0.1)); expect(log.last.dx, closeTo(16.0, 0.1));
await gesture.up(); await gesture.up();
}); });
...@@ -546,20 +546,6 @@ void main() { ...@@ -546,20 +546,6 @@ void main() {
final ThemeData theme = ThemeData( final ThemeData theme = ThemeData(
platform: TargetPlatform.android, platform: TargetPlatform.android,
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
sliderTheme: const SliderThemeData(
disabledThumbColor: Color(0xff000001),
disabledActiveTickMarkColor: Color(0xff000002),
disabledActiveTrackColor: Color(0xff000003),
disabledInactiveTickMarkColor: Color(0xff000004),
disabledInactiveTrackColor: Color(0xff000005),
activeTrackColor: Color(0xff000006),
activeTickMarkColor: Color(0xff000007),
inactiveTrackColor: Color(0xff000008),
inactiveTickMarkColor: Color(0xff000009),
overlayColor: Color(0xff000010),
thumbColor: Color(0xff000011),
valueIndicatorColor: Color(0xff000012),
)
); );
final SliderThemeData sliderTheme = theme.sliderTheme; final SliderThemeData sliderTheme = theme.sliderTheme;
double value = 0.45; double value = 0.45;
...@@ -738,7 +724,7 @@ void main() { ...@@ -738,7 +724,7 @@ void main() {
paints paints
..rect(color: customColor1) // active track ..rect(color: customColor1) // active track
..rect(color: customColor2) // inactive track ..rect(color: customColor2) // inactive track
..circle(color: customColor1.withOpacity(0.12)) // overlay ..circle(color: customColor1.withAlpha(0x29)) // overlay
..circle(color: customColor2) // 1st tick mark ..circle(color: customColor2) // 1st tick mark
..circle(color: customColor2) // 2nd tick mark ..circle(color: customColor2) // 2nd tick mark
..circle(color: customColor2) // 3rd tick mark ..circle(color: customColor2) // 3rd tick mark
...@@ -872,7 +858,7 @@ void main() { ...@@ -872,7 +858,7 @@ void main() {
), ),
), ),
)); ));
expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 24.0, 600.0)); expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 16.0, 600.0));
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -892,7 +878,7 @@ void main() { ...@@ -892,7 +878,7 @@ void main() {
), ),
), ),
)); ));
expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 24.0, 48.0)); expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 16.0, 32.0));
}); });
testWidgets('Slider respects textScaleFactor', (WidgetTester tester) async { testWidgets('Slider respects textScaleFactor', (WidgetTester tester) async {
...@@ -1091,12 +1077,12 @@ void main() { ...@@ -1091,12 +1077,12 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 25.0, y: 24.0, radius: 1.0) ..circle(x: 17.0, y: 16.0, radius: 1.0)
..circle(x: 212.5, y: 24.0, radius: 1.0) ..circle(x: 208.5, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 1.0) ..circle(x: 400.0, y: 16.0, radius: 1.0)
..circle(x: 587.5, y: 24.0, radius: 1.0) ..circle(x: 591.5, y: 16.0, radius: 1.0)
..circle(x: 775.0, y: 24.0, radius: 1.0) ..circle(x: 783.0, y: 16.0, radius: 1.0)
..circle(x: 24.0, y: 24.0, radius: 10.0), ..circle(x: 16.0, y: 16.0, radius: 6.0),
); );
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
...@@ -1107,13 +1093,13 @@ void main() { ...@@ -1107,13 +1093,13 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 111.20703125, y: 24.0, radius: 5.687664985656738) ..circle(x: 105.0625, y: 16.0, radius: 3.791776657104492)
..circle(x: 25.0, y: 24.0, radius: 1.0) ..circle(x: 17.0, y: 16.0, radius: 1.0)
..circle(x: 212.5, y: 24.0, radius: 1.0) ..circle(x: 208.5, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 1.0) ..circle(x: 400.0, y: 16.0, radius: 1.0)
..circle(x: 587.5, y: 24.0, radius: 1.0) ..circle(x: 591.5, y: 16.0, radius: 1.0)
..circle(x: 775.0, y: 24.0, radius: 1.0) ..circle(x: 783.0, y: 16.0, radius: 1.0)
..circle(x: 111.20703125, y: 24.0, radius: 10.0), ..circle(x: 105.0625, y: 16.0, radius: 6.0),
); );
// Reparenting in the middle of an animation should do nothing. // Reparenting in the middle of an animation should do nothing.
...@@ -1127,13 +1113,13 @@ void main() { ...@@ -1127,13 +1113,13 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 190.0135726928711, y: 24.0, radius: 12.0) ..circle(x: 185.5457763671875, y: 16.0, radius: 8.0)
..circle(x: 25.0, y: 24.0, radius: 1.0) ..circle(x: 17.0, y: 16.0, radius: 1.0)
..circle(x: 212.5, y: 24.0, radius: 1.0) ..circle(x: 208.5, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 1.0) ..circle(x: 400.0, y: 16.0, radius: 1.0)
..circle(x: 587.5, y: 24.0, radius: 1.0) ..circle(x: 591.5, y: 16.0, radius: 1.0)
..circle(x: 775.0, y: 24.0, radius: 1.0) ..circle(x: 783.0, y: 16.0, radius: 1.0)
..circle(x: 190.0135726928711, y: 24.0, radius: 10.0), ..circle(x: 185.5457763671875, y: 16.0, radius: 6.0),
); );
// Wait for animations to finish. // Wait for animations to finish.
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -1141,13 +1127,13 @@ void main() { ...@@ -1141,13 +1127,13 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 400.0, y: 24.0, radius: 24.0) ..circle(x: 400.0, y: 16.0, radius: 16.0)
..circle(x: 25.0, y: 24.0, radius: 1.0) ..circle(x: 17.0, y: 16.0, radius: 1.0)
..circle(x: 212.5, y: 24.0, radius: 1.0) ..circle(x: 208.5, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 1.0) ..circle(x: 400.0, y: 16.0, radius: 1.0)
..circle(x: 587.5, y: 24.0, radius: 1.0) ..circle(x: 591.5, y: 16.0, radius: 1.0)
..circle(x: 775.0, y: 24.0, radius: 1.0) ..circle(x: 783.0, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 10.0), ..circle(x: 400.0, y: 16.0, radius: 6.0),
); );
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -1155,12 +1141,12 @@ void main() { ...@@ -1155,12 +1141,12 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 25.0, y: 24.0, radius: 1.0) ..circle(x: 17.0, y: 16.0, radius: 1.0)
..circle(x: 212.5, y: 24.0, radius: 1.0) ..circle(x: 208.5, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 1.0) ..circle(x: 400.0, y: 16.0, radius: 1.0)
..circle(x: 587.5, y: 24.0, radius: 1.0) ..circle(x: 591.5, y: 16.0, radius: 1.0)
..circle(x: 775.0, y: 24.0, radius: 1.0) ..circle(x: 783.0, y: 16.0, radius: 1.0)
..circle(x: 400.0, y: 24.0, radius: 10.0), ..circle(x: 400.0, y: 16.0, radius: 6.0),
); );
} }
......
...@@ -12,6 +12,17 @@ import 'package:flutter/painting.dart'; ...@@ -12,6 +12,17 @@ import 'package:flutter/painting.dart';
import '../rendering/mock_canvas.dart'; import '../rendering/mock_canvas.dart';
void main() { void main() {
testWidgets('Slider theme is built by ThemeData', (WidgetTester tester) async {
final ThemeData theme = ThemeData(
platform: TargetPlatform.android,
primarySwatch: Colors.red,
);
final SliderThemeData sliderTheme = theme.sliderTheme;
expect(sliderTheme.activeTrackColor.value, equals(Colors.red.value));
expect(sliderTheme.inactiveTrackColor.value, equals(Colors.red.withAlpha(0x3d).value));
});
testWidgets('Slider uses ThemeData slider theme if present', (WidgetTester tester) async { testWidgets('Slider uses ThemeData slider theme if present', (WidgetTester tester) async {
final ThemeData theme = ThemeData( final ThemeData theme = ThemeData(
platform: TargetPlatform.android, platform: TargetPlatform.android,
...@@ -52,6 +63,20 @@ void main() { ...@@ -52,6 +63,20 @@ void main() {
); );
}); });
testWidgets('SliderThemeData assigns the correct default shapes', (WidgetTester tester) async {
final SliderThemeData sliderTheme = ThemeData().sliderTheme;
expect(sliderTheme.trackShape, equals(isInstanceOf<RectangularSliderTrackShape>()));
expect(sliderTheme.tickMarkShape, equals(isInstanceOf<RoundSliderTickMarkShape>()));
expect(sliderTheme.thumbShape, equals(isInstanceOf<RoundSliderThumbShape>()));
expect(sliderTheme.valueIndicatorShape, equals(isInstanceOf<PaddleSliderValueIndicatorShape>()));
expect(sliderTheme.overlayShape, equals(isInstanceOf<RoundSliderOverlayShape>()));
});
testWidgets('SliderThemeData assigns the correct default flags', (WidgetTester tester) async {
final SliderThemeData sliderTheme = ThemeData().sliderTheme;
expect(sliderTheme.showValueIndicator, equals(ShowValueIndicator.onlyForDiscrete));
});
testWidgets('SliderThemeData generates correct opacities for fromPrimaryColors', (WidgetTester tester) async { testWidgets('SliderThemeData generates correct opacities for fromPrimaryColors', (WidgetTester tester) async {
const Color customColor1 = Color(0xcafefeed); const Color customColor1 = Color(0xcafefeed);
const Color customColor2 = Color(0xdeadbeef); const Color customColor2 = Color(0xdeadbeef);
...@@ -75,7 +100,7 @@ void main() { ...@@ -75,7 +100,7 @@ void main() {
expect(sliderTheme.disabledInactiveTickMarkColor, equals(customColor2.withAlpha(0x1f))); expect(sliderTheme.disabledInactiveTickMarkColor, equals(customColor2.withAlpha(0x1f)));
expect(sliderTheme.thumbColor, equals(customColor1.withAlpha(0xff))); expect(sliderTheme.thumbColor, equals(customColor1.withAlpha(0xff)));
expect(sliderTheme.disabledThumbColor, equals(customColor2.withAlpha(0x52))); expect(sliderTheme.disabledThumbColor, equals(customColor2.withAlpha(0x52)));
expect(sliderTheme.overlayColor, equals(customColor1.withAlpha(0x1f))); expect(sliderTheme.overlayColor, equals(customColor1.withAlpha(0x29)));
expect(sliderTheme.valueIndicatorColor, equals(customColor1.withAlpha(0xff))); expect(sliderTheme.valueIndicatorColor, equals(customColor1.withAlpha(0xff)));
expect(sliderTheme.valueIndicatorTextStyle.color, equals(customColor4)); expect(sliderTheme.valueIndicatorTextStyle.color, equals(customColor4));
}); });
...@@ -107,7 +132,7 @@ void main() { ...@@ -107,7 +132,7 @@ void main() {
expect(lerp.disabledInactiveTickMarkColor, equals(middleGrey.withAlpha(0x1f))); expect(lerp.disabledInactiveTickMarkColor, equals(middleGrey.withAlpha(0x1f)));
expect(lerp.thumbColor, equals(middleGrey.withAlpha(0xff))); expect(lerp.thumbColor, equals(middleGrey.withAlpha(0xff)));
expect(lerp.disabledThumbColor, equals(middleGrey.withAlpha(0x52))); expect(lerp.disabledThumbColor, equals(middleGrey.withAlpha(0x52)));
expect(lerp.overlayColor, equals(middleGrey.withAlpha(0x1f))); expect(lerp.overlayColor, equals(middleGrey.withAlpha(0x29)));
expect(lerp.valueIndicatorColor, equals(middleGrey.withAlpha(0xff))); expect(lerp.valueIndicatorColor, equals(middleGrey.withAlpha(0xff)));
expect(lerp.valueIndicatorTextStyle.color, equals(middleGrey.withAlpha(0xff))); expect(lerp.valueIndicatorTextStyle.color, equals(middleGrey.withAlpha(0xff)));
}); });
...@@ -127,8 +152,8 @@ void main() { ...@@ -127,8 +152,8 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..rect(rect: Rect.fromLTRB(25.0, 299.0, 202.0, 301.0), color: sliderTheme.activeTrackColor) ..rect(rect: Rect.fromLTRB(16.0, 299.0, 208.0, 301.0), color: sliderTheme.activeTrackColor)
..rect(rect: Rect.fromLTRB(222.0, 299.0, 776.0, 301.0), color: sliderTheme.inactiveTrackColor), ..rect(rect: Rect.fromLTRB(208.0, 299.0, 784.0, 301.0), color: sliderTheme.inactiveTrackColor),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
...@@ -143,8 +168,8 @@ void main() { ...@@ -143,8 +168,8 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..rect(rect: Rect.fromLTRB(25.0, 299.0, 202.0, 301.0), color: sliderTheme.disabledActiveTrackColor) ..rect(rect: Rect.fromLTRB(16.0, 299.0, 202.0, 301.0), color: sliderTheme.disabledActiveTrackColor)
..rect(rect: Rect.fromLTRB(222.0, 299.0, 776.0, 301.0), color: sliderTheme.disabledInactiveTrackColor), ..rect(rect: Rect.fromLTRB(214.0, 299.0, 784.0, 301.0), color: sliderTheme.disabledInactiveTrackColor),
); );
}); });
...@@ -164,9 +189,9 @@ void main() { ...@@ -164,9 +189,9 @@ void main() {
paints paints
..circle( ..circle(
color: sliderTheme.thumbColor, color: sliderTheme.thumbColor,
x: 212.0, x: 208.0,
y: 300.0, y: 300.0,
radius: 10.0, radius: 6.0,
), ),
); );
...@@ -181,15 +206,15 @@ void main() { ...@@ -181,15 +206,15 @@ void main() {
paints paints
..circle( ..circle(
color: sliderTheme.overlayColor, color: sliderTheme.overlayColor,
x: 212.0, x: 208.0,
y: 300.0, y: 300.0,
radius: 24.0, radius: 16.0,
) )
..circle( ..circle(
color: sliderTheme.thumbColor, color: sliderTheme.thumbColor,
x: 212.0, x: 208.0,
y: 300.0, y: 300.0,
radius: 10.0, radius: 6.0,
), ),
); );
...@@ -202,9 +227,9 @@ void main() { ...@@ -202,9 +227,9 @@ void main() {
paints paints
..circle( ..circle(
color: sliderTheme.thumbColor, color: sliderTheme.thumbColor,
x: 212.0, x: 208.0,
y: 300.0, y: 300.0,
radius: 10.0, radius: 6.0,
), ),
); );
}); });
...@@ -219,12 +244,12 @@ void main() { ...@@ -219,12 +244,12 @@ void main() {
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45));
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider)); final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
expect(sliderBox, paints..circle(color: sliderTheme.thumbColor, radius: 10.0)); expect(sliderBox, paints..circle(color: sliderTheme.thumbColor, radius: 6.0));
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, enabled: false));
await tester.pumpAndSettle(); // wait for disable animation await tester.pumpAndSettle(); // wait for disable animation
expect(sliderBox, paints..circle(color: sliderTheme.disabledThumbColor, radius: 10.0)); expect(sliderBox, paints..circle(color: sliderTheme.disabledThumbColor, radius: 4.0));
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3));
await tester.pumpAndSettle(); // wait for enable animation await tester.pumpAndSettle(); // wait for enable animation
...@@ -236,7 +261,7 @@ void main() { ...@@ -236,7 +261,7 @@ void main() {
..circle(color: sliderTheme.activeTickMarkColor) ..circle(color: sliderTheme.activeTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor) ..circle(color: sliderTheme.inactiveTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor) ..circle(color: sliderTheme.inactiveTickMarkColor)
..circle(color: sliderTheme.thumbColor, radius: 10.0), ..circle(color: sliderTheme.thumbColor, radius: 6.0),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3, enabled: false));
...@@ -249,7 +274,7 @@ void main() { ...@@ -249,7 +274,7 @@ void main() {
..circle(color: sliderTheme.disabledInactiveTickMarkColor) ..circle(color: sliderTheme.disabledInactiveTickMarkColor)
..circle(color: sliderTheme.disabledInactiveTickMarkColor) ..circle(color: sliderTheme.disabledInactiveTickMarkColor)
..circle(color: sliderTheme.disabledInactiveTickMarkColor) ..circle(color: sliderTheme.disabledInactiveTickMarkColor)
..circle(color: sliderTheme.disabledThumbColor, radius: 10.0), ..circle(color: sliderTheme.disabledThumbColor, radius: 4.0),
); );
}); });
...@@ -343,10 +368,10 @@ void main() { ...@@ -343,10 +368,10 @@ void main() {
color: sliderTheme.valueIndicatorColor, color: sliderTheme.valueIndicatorColor,
includes: <Offset>[ includes: <Offset>[
const Offset(0.0, -40.0), const Offset(0.0, -40.0),
const Offset(92.0, -40.0), const Offset(98.0, -40.0),
const Offset(-16.0, -40.0), const Offset(-16.0, -40.0),
], ],
excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-20.1, -40.0)], excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-16.1, -40.0)],
), ),
); );
await gesture.up(); await gesture.up();
...@@ -365,9 +390,9 @@ void main() { ...@@ -365,9 +390,9 @@ void main() {
includes: <Offset>[ includes: <Offset>[
const Offset(0.0, -40.0), const Offset(0.0, -40.0),
const Offset(16.0, -40.0), const Offset(16.0, -40.0),
const Offset(-92.0, -40.0), const Offset(-98.0, -40.0),
], ],
excludes: <Offset>[const Offset(20.1, -40.0), const Offset(-98.1, -40.0)], excludes: <Offset>[const Offset(16.1, -40.0), const Offset(-98.1, -40.0)],
), ),
); );
await gesture.up(); await gesture.up();
...@@ -385,14 +410,14 @@ void main() { ...@@ -385,14 +410,14 @@ void main() {
color: sliderTheme.valueIndicatorColor, color: sliderTheme.valueIndicatorColor,
includes: <Offset>[ includes: <Offset>[
const Offset(0.0, -49.0), const Offset(0.0, -49.0),
const Offset(68.0, -49.0), const Offset(90.0, -49.0),
const Offset(-24.0, -49.0), const Offset(-24.0, -49.0),
], ],
excludes: <Offset>[ excludes: <Offset>[
const Offset(98.0, -32.0), // inside full size, outside small const Offset(98.0, -32.0), // inside full size, outside small
const Offset(-40.0, -32.0), // inside full size, outside small const Offset(-16.0, -32.0), // inside full size, outside small
const Offset(90.1, -49.0), const Offset(90.1, -49.0),
const Offset(-40.1, -49.0), const Offset(-24.1, -49.0),
], ],
), ),
); );
...@@ -411,9 +436,10 @@ void main() { ...@@ -411,9 +436,10 @@ void main() {
color: sliderTheme.valueIndicatorColor, color: sliderTheme.valueIndicatorColor,
includes: <Offset>[ includes: <Offset>[
const Offset(0.0, -38.8), const Offset(0.0, -38.8),
const Offset(92.0, -38.8), const Offset(98.0, -38.8),
const Offset(8.0, -23.0), // Inside large, outside scale=1.0 const Offset(-16.0, -38.8),
const Offset(-2.0, -23.0), // Inside large, outside scale=1.0 const Offset(10.0, -23.0), // Inside large, outside scale=1.0
const Offset(-4.0, -23.0), // Inside large, outside scale=1.0
], ],
excludes: <Offset>[ excludes: <Offset>[
const Offset(98.5, -38.8), const Offset(98.5, -38.8),
...@@ -435,8 +461,8 @@ void main() { ...@@ -435,8 +461,8 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..rect(rect: Rect.fromLTRB(32.0, 292.0, 202.0, 308.0), color: sliderTheme.activeTrackColor) ..rect(rect: Rect.fromLTRB(16.0, 292.0, 208.0, 308.0), color: sliderTheme.activeTrackColor)
..rect(rect: Rect.fromLTRB(222.0, 292.0, 776.0, 308.0), color: sliderTheme.inactiveTrackColor), ..rect(rect: Rect.fromLTRB(208.0, 292.0, 784.0, 308.0), color: sliderTheme.inactiveTrackColor),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
...@@ -447,8 +473,8 @@ void main() { ...@@ -447,8 +473,8 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..rect(rect: Rect.fromLTRB(32.0, 292.0, 202.0, 308.0), color: sliderTheme.disabledActiveTrackColor) ..rect(rect: Rect.fromLTRB(16.0, 292.0, 202.0, 308.0), color: sliderTheme.disabledActiveTrackColor)
..rect(rect: Rect.fromLTRB(222.0, 292.0, 776.0, 308.0), color: sliderTheme.disabledInactiveTrackColor), ..rect(rect: Rect.fromLTRB(214.0, 292.0, 784.0, 308.0), color: sliderTheme.disabledInactiveTrackColor),
); );
}); });
...@@ -465,7 +491,7 @@ void main() { ...@@ -465,7 +491,7 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints..circle(x: 212, y: 300, radius: 7, color: sliderTheme.thumbColor), paints..circle(x: 208, y: 300, radius: 7, color: sliderTheme.thumbColor),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
...@@ -473,7 +499,7 @@ void main() { ...@@ -473,7 +499,7 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints..circle(x: 212, y: 300, radius: 11, color: sliderTheme.disabledThumbColor), paints..circle(x: 208, y: 300, radius: 11, color: sliderTheme.disabledThumbColor),
); );
}); });
...@@ -489,21 +515,26 @@ void main() { ...@@ -489,21 +515,26 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints..circle(x: 212, y: 300, radius: 9, color: sliderTheme.thumbColor), paints..circle(x: 208, y: 300, radius: 9, color: sliderTheme.thumbColor),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
await tester.pumpAndSettle(); // wait for disable animation await tester.pumpAndSettle(); // wait for disable animation
// Radius should be 6, or 2/3 of 9. 2/3 because the default disabled thumb
// radius is 4 and the default enabled thumb radius is 6.
// TODO(clocksmith): This ratio will change once thumb sizes are updated to spec.
expect( expect(
sliderBox, sliderBox,
paints..circle(x: 212, y: 300, radius: 9, color: sliderTheme.disabledThumbColor), paints..circle(x: 208, y: 300, radius: 6, color: sliderTheme.disabledThumbColor),
); );
}); });
testWidgets('The default slider tick mark shape size can be overridden', (WidgetTester tester) async { testWidgets('The default slider tick mark shape size can be overridden', (WidgetTester tester) async {
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith( final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
tickMarkShape: const RoundSliderTickMarkShape(tickMarkRadius: 5), tickMarkShape: const RoundSliderTickMarkShape(
tickMarkRadius: 5
),
activeTickMarkColor: const Color(0xfadedead), activeTickMarkColor: const Color(0xfadedead),
inactiveTickMarkColor: const Color(0xfadebeef), inactiveTickMarkColor: const Color(0xfadebeef),
disabledActiveTickMarkColor: const Color(0xfadecafe), disabledActiveTickMarkColor: const Color(0xfadecafe),
...@@ -517,9 +548,9 @@ void main() { ...@@ -517,9 +548,9 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 29, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor) ..circle(x: 21, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor)
..circle(x: 400, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor) ..circle(x: 400, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor)
..circle(x: 771, y: 300, radius: 5, color: sliderTheme.inactiveTickMarkColor), ..circle(x: 779, y: 300, radius: 5, color: sliderTheme.inactiveTickMarkColor),
); );
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2, enabled: false)); await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2, enabled: false));
...@@ -528,9 +559,9 @@ void main() { ...@@ -528,9 +559,9 @@ void main() {
expect( expect(
sliderBox, sliderBox,
paints paints
..circle(x: 29, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor) ..circle(x: 21, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor)
..circle(x: 400, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor) ..circle(x: 400, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor)
..circle(x: 771, y: 300, radius: 5, color: sliderTheme.disabledInactiveTickMarkColor), ..circle(x: 779, y: 300, radius: 5, color: sliderTheme.disabledInactiveTickMarkColor),
); );
}); });
......
...@@ -56,6 +56,16 @@ void main() { ...@@ -56,6 +56,16 @@ void main() {
expect(darkTheme.accentTextTheme.title.color, typography.white.title.color); expect(darkTheme.accentTextTheme.title.color, typography.white.title.color);
}); });
test('Default slider indicator style gets a default body2 if accentTextTheme.body2 is null', () {
const TextTheme noBody2TextTheme = TextTheme(body2: null);
final ThemeData lightTheme = ThemeData(brightness: Brightness.light, accentTextTheme: noBody2TextTheme);
final ThemeData darkTheme = ThemeData(brightness: Brightness.dark, accentTextTheme: noBody2TextTheme);
final Typography typography = Typography(platform: lightTheme.platform);
expect(lightTheme.sliderTheme.valueIndicatorTextStyle, equals(typography.white.body2));
expect(darkTheme.sliderTheme.valueIndicatorTextStyle, equals(typography.black.body2));
});
test('Default chip label style gets a default body2 if textTheme.body2 is null', () { test('Default chip label style gets a default body2 if textTheme.body2 is null', () {
const TextTheme noBody2TextTheme = TextTheme(body2: null); const TextTheme noBody2TextTheme = TextTheme(body2: null);
final ThemeData lightTheme = ThemeData(brightness: Brightness.light, textTheme: noBody2TextTheme); final ThemeData lightTheme = ThemeData(brightness: Brightness.light, textTheme: noBody2TextTheme);
......
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