Unverified Commit 10fe2056 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add a slider demo, and a text theme for SliderThemeData (#15620)

This adds a slider demo with a custom theme to the gallery.

In the process of adding this, I decided to add a text theme to the SliderThemeData, since it's a pain to change the text style on the value indicator otherwise.
parent 7a285301
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SliderDemo extends StatefulWidget { class SliderDemo extends StatefulWidget {
...@@ -11,12 +13,124 @@ class SliderDemo extends StatefulWidget { ...@@ -11,12 +13,124 @@ class SliderDemo extends StatefulWidget {
_SliderDemoState createState() => new _SliderDemoState(); _SliderDemoState createState() => new _SliderDemoState();
} }
Path _triangle(double size, Offset thumbCenter, {bool invert: false}) {
final Path thumbPath = new Path();
final double height = math.sqrt(3.0) / 2.0;
final double halfSide = size / 2.0;
final double centerHeight = size * height / 3.0;
final double sign = invert ? -1.0 : 1.0;
thumbPath.moveTo(thumbCenter.dx - halfSide, thumbCenter.dy + sign * centerHeight);
thumbPath.lineTo(thumbCenter.dx, thumbCenter.dy - 2.0 * sign * centerHeight);
thumbPath.lineTo(thumbCenter.dx + halfSide, thumbCenter.dy + sign * centerHeight);
thumbPath.close();
return thumbPath;
}
class _CustomThumbShape extends SliderComponentShape {
static const double _thumbSize = 4.0;
static const double _disabledThumbSize = 3.0;
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return isEnabled ? const Size.fromRadius(_thumbSize) : const Size.fromRadius(_disabledThumbSize);
}
static final Tween<double> sizeTween = new Tween<double>(
begin: _disabledThumbSize,
end: _thumbSize,
);
@override
void paint(
PaintingContext context,
Offset thumbCenter, {
Animation<double> activationAnimation,
Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme,
TextDirection textDirection,
double value,
}) {
final Canvas canvas = context.canvas;
final ColorTween colorTween = new ColorTween(
begin: sliderTheme.disabledThumbColor,
end: sliderTheme.thumbColor,
);
final double size = _thumbSize * sizeTween.evaluate(enableAnimation);
final Path thumbPath = _triangle(size, thumbCenter);
canvas.drawPath(thumbPath, new Paint()..color = colorTween.evaluate(enableAnimation));
}
}
class _CustomValueIndicatorShape extends SliderComponentShape {
static const double _indicatorSize = 4.0;
static const double _disabledIndicatorSize = 3.0;
static const double _slideUpHeight = 40.0;
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return new Size.fromRadius(isEnabled ? _indicatorSize : _disabledIndicatorSize);
}
static final Tween<double> sizeTween = new Tween<double>(
begin: _disabledIndicatorSize,
end: _indicatorSize,
);
@override
void paint(
PaintingContext context,
Offset thumbCenter, {
Animation<double> activationAnimation,
Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme,
TextDirection textDirection,
double value,
}) {
final Canvas canvas = context.canvas;
final ColorTween enableColor = new ColorTween(
begin: sliderTheme.disabledThumbColor,
end: sliderTheme.valueIndicatorColor,
);
final Tween<double> slideUpTween = new Tween<double>(
begin: 0.0,
end: _slideUpHeight,
);
final double size = _indicatorSize * sizeTween.evaluate(enableAnimation);
final Offset slideUpOffset = new Offset(0.0, -slideUpTween.evaluate(activationAnimation));
final Path thumbPath = _triangle(
size,
thumbCenter + slideUpOffset,
invert: true,
);
final Color paintColor = enableColor.evaluate(enableAnimation).withAlpha((255.0 * activationAnimation.value).round());
canvas.drawPath(
thumbPath,
new Paint()..color = paintColor,
);
canvas.drawLine(
thumbCenter,
thumbCenter + slideUpOffset,
new Paint()
..color = paintColor
..style = PaintingStyle.stroke
..strokeWidth = 2.0);
labelPainter.paint(canvas, thumbCenter + slideUpOffset + new Offset(-labelPainter.width / 2.0, -labelPainter.height - 4.0));
}
}
class _SliderDemoState extends State<SliderDemo> { class _SliderDemoState extends State<SliderDemo> {
double _value = 25.0; double _value = 25.0;
double _discreteValue = 20.0; double _discreteValue = 20.0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
return new Scaffold( return new Scaffold(
appBar: new AppBar(title: const Text('Sliders')), appBar: new AppBar(title: const Text('Sliders')),
body: new Padding( body: new Padding(
...@@ -26,7 +140,7 @@ class _SliderDemoState extends State<SliderDemo> { ...@@ -26,7 +140,7 @@ class _SliderDemoState extends State<SliderDemo> {
children: <Widget>[ children: <Widget>[
new Column( new Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget> [ children: <Widget>[
new Slider( new Slider(
value: _value, value: _value,
min: 0.0, min: 0.0,
...@@ -35,21 +149,21 @@ class _SliderDemoState extends State<SliderDemo> { ...@@ -35,21 +149,21 @@ class _SliderDemoState extends State<SliderDemo> {
setState(() { setState(() {
_value = value; _value = value;
}); });
} },
), ),
const Text('Continuous'), const Text('Continuous'),
] ],
), ),
new Column( new Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: const <Widget> [ children: const <Widget>[
const Slider(value: 0.25, onChanged: null), const Slider(value: 0.25, onChanged: null),
const Text('Disabled'), const Text('Disabled'),
] ],
), ),
new Column( new Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget> [ children: <Widget>[
new Slider( new Slider(
value: _discreteValue, value: _discreteValue,
min: 0.0, min: 0.0,
...@@ -60,11 +174,43 @@ class _SliderDemoState extends State<SliderDemo> { ...@@ -60,11 +174,43 @@ class _SliderDemoState extends State<SliderDemo> {
setState(() { setState(() {
_discreteValue = value; _discreteValue = value;
}); });
} },
), ),
const Text('Discrete'), const Text('Discrete'),
], ],
), ),
new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new SliderTheme(
data: theme.sliderTheme.copyWith(
activeRailColor: Colors.deepPurple,
inactiveRailColor: Colors.black26,
activeTickMarkColor: Colors.white70,
inactiveTickMarkColor: Colors.black,
overlayColor: Colors.black12,
thumbColor: Colors.deepPurple,
valueIndicatorColor: Colors.deepPurpleAccent,
thumbShape: new _CustomThumbShape(),
valueIndicatorShape: new _CustomValueIndicatorShape(),
valueIndicatorTextStyle: theme.accentTextTheme.body2.copyWith(color: Colors.black87),
),
child: new Slider(
value: _discreteValue,
min: 0.0,
max: 100.0,
divisions: 5,
label: '${_discreteValue.round()}',
onChanged: (double value) {
setState(() {
_discreteValue = value;
});
},
),
),
const Text('Discrete with Custom Theme'),
],
),
], ],
), ),
), ),
......
...@@ -578,7 +578,10 @@ class _RenderSlider extends RenderBox { ...@@ -578,7 +578,10 @@ class _RenderSlider extends RenderBox {
void _updateLabelPainter() { void _updateLabelPainter() {
if (label != null) { if (label != null) {
_labelPainter _labelPainter
..text = new TextSpan(style: _theme.accentTextTheme.body2, text: label) ..text = new TextSpan(
style: _sliderTheme.valueIndicatorTextStyle,
text: label,
)
..textDirection = textDirection ..textDirection = textDirection
..textScaleFactor = _mediaQueryData.textScaleFactor ..textScaleFactor = _mediaQueryData.textScaleFactor
..layout(); ..layout();
...@@ -849,31 +852,31 @@ class _RenderSlider extends RenderBox { ...@@ -849,31 +852,31 @@ class _RenderSlider extends RenderBox {
_valueIndicatorAnimation.status != AnimationStatus.dismissed) { _valueIndicatorAnimation.status != AnimationStatus.dismissed) {
if (showValueIndicator) { if (showValueIndicator) {
_sliderTheme.valueIndicatorShape.paint( _sliderTheme.valueIndicatorShape.paint(
this,
context, context,
isDiscrete,
thumbCenter, thumbCenter,
_valueIndicatorAnimation, activationAnimation: _valueIndicatorAnimation,
_enableAnimation, enableAnimation: _enableAnimation,
_labelPainter, isDiscrete: isDiscrete,
_sliderTheme, labelPainter: _labelPainter,
_textDirection, parentBox: this,
value, sliderTheme: _sliderTheme,
textDirection: _textDirection,
value: _value,
); );
} }
} }
_sliderTheme.thumbShape.paint( _sliderTheme.thumbShape.paint(
this,
context, context,
isDiscrete,
thumbCenter, thumbCenter,
_overlayAnimation, activationAnimation: _valueIndicatorAnimation,
_enableAnimation, enableAnimation: _enableAnimation,
label != null ? _labelPainter : null, isDiscrete: isDiscrete,
_sliderTheme, labelPainter: _labelPainter,
_textDirection, parentBox: this,
value, sliderTheme: _sliderTheme,
textDirection: _textDirection,
value: _value,
); );
} }
......
...@@ -35,9 +35,9 @@ class SliderTheme extends InheritedWidget { ...@@ -35,9 +35,9 @@ class SliderTheme extends InheritedWidget {
Key key, Key key,
@required this.data, @required this.data,
@required Widget child, @required Widget child,
}) : assert(child != null), }) : assert(child != null),
assert(data != null), assert(data != null),
super(key: key, child: child); super(key: key, child: child);
/// Specifies the color and shape values for descendant slider widgets. /// Specifies the color and shape values for descendant slider widgets.
final SliderThemeData data; final SliderThemeData data;
...@@ -194,21 +194,23 @@ class SliderThemeData extends Diagnosticable { ...@@ -194,21 +194,23 @@ class SliderThemeData extends Diagnosticable {
@required this.thumbShape, @required this.thumbShape,
@required this.valueIndicatorShape, @required this.valueIndicatorShape,
@required this.showValueIndicator, @required this.showValueIndicator,
}) : assert(activeRailColor != null), @required this.valueIndicatorTextStyle,
assert(inactiveRailColor != null), }) : assert(activeRailColor != null),
assert(disabledActiveRailColor != null), assert(inactiveRailColor != null),
assert(disabledInactiveRailColor != null), assert(disabledActiveRailColor != null),
assert(activeTickMarkColor != null), assert(disabledInactiveRailColor != null),
assert(inactiveTickMarkColor != null), assert(activeTickMarkColor != null),
assert(disabledActiveTickMarkColor != null), assert(inactiveTickMarkColor != null),
assert(disabledInactiveTickMarkColor != null), assert(disabledActiveTickMarkColor != null),
assert(thumbColor != null), assert(disabledInactiveTickMarkColor != null),
assert(disabledThumbColor != null), assert(thumbColor != null),
assert(overlayColor != null), assert(disabledThumbColor != null),
assert(valueIndicatorColor != null), assert(overlayColor != null),
assert(thumbShape != null), assert(valueIndicatorColor != null),
assert(valueIndicatorShape != null), assert(thumbShape != null),
assert(showValueIndicator != null); assert(valueIndicatorShape != null),
assert(valueIndicatorTextStyle != null),
assert(showValueIndicator != null);
/// Generates a SliderThemeData from three main colors. /// Generates a SliderThemeData from three main colors.
/// ///
...@@ -223,10 +225,12 @@ class SliderThemeData extends Diagnosticable { ...@@ -223,10 +225,12 @@ class SliderThemeData extends Diagnosticable {
@required Color primaryColor, @required Color primaryColor,
@required Color primaryColorDark, @required Color primaryColorDark,
@required Color primaryColorLight, @required Color primaryColorLight,
@required TextStyle valueIndicatorTextStyle,
}) { }) {
assert(primaryColor != null); assert(primaryColor != null);
assert(primaryColorDark != null); assert(primaryColorDark != null);
assert(primaryColorLight != null); assert(primaryColorLight != null);
assert(valueIndicatorTextStyle != null);
// These are Material Design defaults, and are used to derive // These are Material Design defaults, and are used to derive
// component Colors (with opacity) from base colors. // component Colors (with opacity) from base colors.
...@@ -264,6 +268,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -264,6 +268,7 @@ class SliderThemeData extends Diagnosticable {
valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha), valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha),
thumbShape: const RoundSliderThumbShape(), thumbShape: const RoundSliderThumbShape(),
valueIndicatorShape: const PaddleSliderValueIndicatorShape(), valueIndicatorShape: const PaddleSliderValueIndicatorShape(),
valueIndicatorTextStyle: valueIndicatorTextStyle,
showValueIndicator: ShowValueIndicator.onlyForDiscrete, showValueIndicator: ShowValueIndicator.onlyForDiscrete,
); );
} }
...@@ -337,6 +342,11 @@ class SliderThemeData extends Diagnosticable { ...@@ -337,6 +342,11 @@ class SliderThemeData extends Diagnosticable {
/// when the thumb is being touched. /// when the thumb is being touched.
final ShowValueIndicator showValueIndicator; final ShowValueIndicator showValueIndicator;
/// The text style for the text on the value indicator.
///
/// By default this is the [ThemeData.accentTextTheme.body2] text theme.
final TextStyle valueIndicatorTextStyle;
/// Creates a copy of this object but with the given fields replaced with the /// Creates a copy of this object but with the given fields replaced with the
/// new values. /// new values.
SliderThemeData copyWith({ SliderThemeData copyWith({
...@@ -355,6 +365,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -355,6 +365,7 @@ class SliderThemeData extends Diagnosticable {
SliderComponentShape thumbShape, SliderComponentShape thumbShape,
SliderComponentShape valueIndicatorShape, SliderComponentShape valueIndicatorShape,
ShowValueIndicator showValueIndicator, ShowValueIndicator showValueIndicator,
TextStyle valueIndicatorTextStyle,
}) { }) {
return new SliderThemeData( return new SliderThemeData(
activeRailColor: activeRailColor ?? this.activeRailColor, activeRailColor: activeRailColor ?? this.activeRailColor,
...@@ -372,6 +383,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -372,6 +383,7 @@ class SliderThemeData extends Diagnosticable {
thumbShape: thumbShape ?? this.thumbShape, thumbShape: thumbShape ?? this.thumbShape,
valueIndicatorShape: valueIndicatorShape ?? this.valueIndicatorShape, valueIndicatorShape: valueIndicatorShape ?? this.valueIndicatorShape,
showValueIndicator: showValueIndicator ?? this.showValueIndicator, showValueIndicator: showValueIndicator ?? this.showValueIndicator,
valueIndicatorTextStyle: valueIndicatorTextStyle ?? this.valueIndicatorTextStyle,
); );
} }
...@@ -410,6 +422,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -410,6 +422,7 @@ class SliderThemeData extends Diagnosticable {
thumbShape: t < 0.5 ? a.thumbShape : b.thumbShape, thumbShape: t < 0.5 ? a.thumbShape : b.thumbShape,
valueIndicatorShape: t < 0.5 ? a.valueIndicatorShape : b.valueIndicatorShape, valueIndicatorShape: t < 0.5 ? a.valueIndicatorShape : b.valueIndicatorShape,
showValueIndicator: t < 0.5 ? a.showValueIndicator : b.showValueIndicator, showValueIndicator: t < 0.5 ? a.showValueIndicator : b.showValueIndicator,
valueIndicatorTextStyle: TextStyle.lerp(a.valueIndicatorTextStyle, b.valueIndicatorTextStyle, t),
); );
} }
...@@ -431,6 +444,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -431,6 +444,7 @@ class SliderThemeData extends Diagnosticable {
thumbShape, thumbShape,
valueIndicatorShape, valueIndicatorShape,
showValueIndicator, showValueIndicator,
valueIndicatorTextStyle,
); );
} }
...@@ -457,7 +471,8 @@ class SliderThemeData extends Diagnosticable { ...@@ -457,7 +471,8 @@ class SliderThemeData extends Diagnosticable {
otherData.valueIndicatorColor == valueIndicatorColor && otherData.valueIndicatorColor == valueIndicatorColor &&
otherData.thumbShape == thumbShape && otherData.thumbShape == thumbShape &&
otherData.valueIndicatorShape == valueIndicatorShape && otherData.valueIndicatorShape == valueIndicatorShape &&
otherData.showValueIndicator == showValueIndicator; otherData.showValueIndicator == showValueIndicator &&
otherData.valueIndicatorTextStyle == valueIndicatorTextStyle;
} }
@override @override
...@@ -468,6 +483,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -468,6 +483,7 @@ class SliderThemeData extends Diagnosticable {
primaryColor: defaultTheme.primaryColor, primaryColor: defaultTheme.primaryColor,
primaryColorDark: defaultTheme.primaryColorDark, primaryColorDark: defaultTheme.primaryColorDark,
primaryColorLight: defaultTheme.primaryColorLight, primaryColorLight: defaultTheme.primaryColorLight,
valueIndicatorTextStyle: defaultTheme.accentTextTheme.body2,
); );
description.add(new DiagnosticsProperty<Color>('activeRailColor', activeRailColor, defaultValue: defaultData.activeRailColor)); description.add(new DiagnosticsProperty<Color>('activeRailColor', activeRailColor, defaultValue: defaultData.activeRailColor));
description.add(new DiagnosticsProperty<Color>('inactiveRailColor', inactiveRailColor, defaultValue: defaultData.inactiveRailColor)); description.add(new DiagnosticsProperty<Color>('inactiveRailColor', inactiveRailColor, defaultValue: defaultData.inactiveRailColor));
...@@ -484,6 +500,7 @@ class SliderThemeData extends Diagnosticable { ...@@ -484,6 +500,7 @@ class SliderThemeData extends Diagnosticable {
description.add(new DiagnosticsProperty<SliderComponentShape>('thumbShape', thumbShape, defaultValue: defaultData.thumbShape, level: DiagnosticLevel.debug)); description.add(new DiagnosticsProperty<SliderComponentShape>('thumbShape', thumbShape, defaultValue: defaultData.thumbShape, level: DiagnosticLevel.debug));
description.add(new DiagnosticsProperty<SliderComponentShape>('valueIndicatorShape', valueIndicatorShape, defaultValue: defaultData.valueIndicatorShape, level: DiagnosticLevel.debug)); description.add(new DiagnosticsProperty<SliderComponentShape>('valueIndicatorShape', valueIndicatorShape, defaultValue: defaultData.valueIndicatorShape, level: DiagnosticLevel.debug));
description.add(new EnumProperty<ShowValueIndicator>('showValueIndicator', showValueIndicator, defaultValue: defaultData.showValueIndicator)); description.add(new EnumProperty<ShowValueIndicator>('showValueIndicator', showValueIndicator, defaultValue: defaultData.showValueIndicator));
description.add(new DiagnosticsProperty<TextStyle>('valueIndicatorTextStyle', valueIndicatorTextStyle, defaultValue: defaultData.valueIndicatorTextStyle));
} }
} }
...@@ -510,24 +527,27 @@ abstract class SliderComponentShape { ...@@ -510,24 +527,27 @@ abstract class SliderComponentShape {
/// [activationAnimation] is an animation triggered when the user beings /// [activationAnimation] is an animation triggered when the user beings
/// to interact with the slider. It reverses when the user stops interacting /// to interact with the slider. It reverses when the user stops interacting
/// with the slider. /// with the slider.
///
/// [enableAnimation] is an animation triggered when the [Slider] is enabled, /// [enableAnimation] is an animation triggered when the [Slider] is enabled,
/// and it reverses when the slider is disabled. /// and it reverses when the slider is disabled.
///
/// [value] is the current parametric value (from 0.0 to 1.0) of the slider.
///
/// If [labelPainter] is non-null, then [labelPainter.paint] should be /// If [labelPainter] is non-null, then [labelPainter.paint] should be
/// called with the location that the label should appear. If the labelPainter /// called with the location that the label should appear. If the labelPainter
/// passed is null, then no label was supplied to the [Slider]. /// passed is null, then no label was supplied to the [Slider].
/// [value] is the current parametric value (from 0.0 to 1.0) of the slider.
void paint( void paint(
RenderBox parentBox,
PaintingContext context, PaintingContext context,
bool isDiscrete, Offset thumbCenter, {
Offset thumbCenter,
Animation<double> activationAnimation, Animation<double> activationAnimation,
Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter, TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme, SliderThemeData sliderTheme,
TextDirection textDirection, TextDirection textDirection,
double value, double value,
); });
} }
/// This is the default shape to a [Slider]'s thumb if no /// This is the default shape to a [Slider]'s thumb if no
...@@ -552,17 +572,17 @@ class RoundSliderThumbShape extends SliderComponentShape { ...@@ -552,17 +572,17 @@ class RoundSliderThumbShape extends SliderComponentShape {
@override @override
void paint( void paint(
RenderBox parentBox,
PaintingContext context, PaintingContext context,
bool isDiscrete, Offset thumbCenter, {
Offset thumbCenter,
Animation<double> activationAnimation, Animation<double> activationAnimation,
Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter, TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme, SliderThemeData sliderTheme,
TextDirection textDirection, TextDirection textDirection,
double value, double value,
) { }) {
final Canvas canvas = context.canvas; final Canvas canvas = context.canvas;
final Tween<double> radiusTween = new Tween<double>( final Tween<double> radiusTween = new Tween<double>(
begin: _disabledThumbRadius, begin: _disabledThumbRadius,
...@@ -624,8 +644,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -624,8 +644,7 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
static const double _twoSeventyDegrees = 3.0 * math.pi / 2.0; static const double _twoSeventyDegrees = 3.0 * math.pi / 2.0;
static const double _ninetyDegrees = math.pi / 2.0; static const double _ninetyDegrees = math.pi / 2.0;
static const double _thirtyDegrees = math.pi / 6.0; static const double _thirtyDegrees = math.pi / 6.0;
static const Size _preferredSize = static const Size _preferredSize = const Size.fromHeight(_distanceBetweenTopBottomCenters + _topLobeRadius + _bottomLobeRadius);
const Size.fromHeight(_distanceBetweenTopBottomCenters + _topLobeRadius + _bottomLobeRadius);
// Set to true if you want a rectangle to be drawn around the label bubble. // Set to true if you want a rectangle to be drawn around the label bubble.
// This helps with building tests that check that the label draws in the right // This helps with building tests that check that the label draws in the right
// place (because it prints the rect in the failed test output). It should not // place (because it prints the rect in the failed test output). It should not
...@@ -767,9 +786,11 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -767,9 +786,11 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
double shift = _getIdealOffset(parentBox, halfWidthNeeded, overallScale, center); double shift = _getIdealOffset(parentBox, halfWidthNeeded, overallScale, center);
double leftWidthNeeded; double leftWidthNeeded;
double rightWidthNeeded; double rightWidthNeeded;
if (shift < 0.0) { // shifting to the left if (shift < 0.0) {
// shifting to the left
shift = math.max(shift, -halfWidthNeeded); shift = math.max(shift, -halfWidthNeeded);
} else { // shifting to the right } else {
// shifting to the right
shift = math.min(shift, halfWidthNeeded); shift = math.min(shift, halfWidthNeeded);
} }
rightWidthNeeded = halfWidthNeeded + shift; rightWidthNeeded = halfWidthNeeded + shift;
...@@ -808,21 +829,23 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -808,21 +829,23 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
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 = new Offset(0.0, neckStretchBaseline - stretch); final Offset neckStretch = new Offset(0.0, neckStretchBaseline - stretch);
assert(!_debuggingLabelLocation || () { assert(!_debuggingLabelLocation ||
final Offset leftCenter = _topLobeCenter - new Offset(leftWidthNeeded, 0.0) + neckStretch; () {
final Offset rightCenter = _topLobeCenter + new Offset(rightWidthNeeded, 0.0) + neckStretch; final Offset leftCenter = _topLobeCenter - new Offset(leftWidthNeeded, 0.0) + neckStretch;
final Rect valueRect = new Rect.fromLTRB( final Offset rightCenter = _topLobeCenter + new Offset(rightWidthNeeded, 0.0) + neckStretch;
leftCenter.dx - _topLobeRadius, final Rect valueRect = new Rect.fromLTRB(
leftCenter.dy - _topLobeRadius, leftCenter.dx - _topLobeRadius,
rightCenter.dx + _topLobeRadius, leftCenter.dy - _topLobeRadius,
rightCenter.dy + _topLobeRadius, rightCenter.dx + _topLobeRadius,
); rightCenter.dy + _topLobeRadius,
final Paint outlinePaint = new Paint() );
..color = const Color(0xffff0000) final Paint outlinePaint = new Paint()
..style = PaintingStyle.stroke..strokeWidth = 1.0; ..color = const Color(0xffff0000)
canvas.drawRect(valueRect, outlinePaint); ..style = PaintingStyle.stroke
return true; ..strokeWidth = 1.0;
}()); canvas.drawRect(valueRect, outlinePaint);
return true;
}());
_addArc( _addArc(
path, path,
...@@ -865,18 +888,17 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape { ...@@ -865,18 +888,17 @@ class PaddleSliderValueIndicatorShape extends SliderComponentShape {
@override @override
void paint( void paint(
RenderBox parentBox,
PaintingContext context, PaintingContext context,
bool isDiscrete, Offset thumbCenter, {
Offset thumbCenter,
Animation<double> activationAnimation, Animation<double> activationAnimation,
Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter, TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme, SliderThemeData sliderTheme,
TextDirection textDirection, TextDirection textDirection,
double value, double value,
) { }) {
assert(labelPainter != null);
final ColorTween enableColor = new ColorTween( final ColorTween enableColor = new ColorTween(
begin: sliderTheme.disabledThumbColor, begin: sliderTheme.disabledThumbColor,
end: sliderTheme.valueIndicatorColor, end: sliderTheme.valueIndicatorColor,
......
...@@ -166,6 +166,7 @@ class ThemeData extends Diagnosticable { ...@@ -166,6 +166,7 @@ class ThemeData extends Diagnosticable {
primaryColor: primaryColor, primaryColor: primaryColor,
primaryColorLight: primaryColorLight, primaryColorLight: primaryColorLight,
primaryColorDark: primaryColorDark, primaryColorDark: primaryColorDark,
valueIndicatorTextStyle: accentTextTheme.body2,
); );
return new ThemeData.raw( return new ThemeData.raw(
brightness: brightness, brightness: brightness,
......
...@@ -25,17 +25,17 @@ class LoggingThumbShape extends SliderComponentShape { ...@@ -25,17 +25,17 @@ class LoggingThumbShape extends SliderComponentShape {
@override @override
void paint( void paint(
RenderBox parentBox,
PaintingContext context, PaintingContext context,
bool isDiscrete, Offset thumbCenter, {
Offset thumbCenter,
Animation<double> activationAnimation, Animation<double> activationAnimation,
Animation<double> enableAnimation, Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter, TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme, SliderThemeData sliderTheme,
TextDirection textDirection, TextDirection textDirection,
double value, double value,
) { }) {
log.add(thumbCenter); log.add(thumbCenter);
final Paint thumbPaint = new Paint()..color = Colors.red; final Paint thumbPaint = new Paint()..color = Colors.red;
context.canvas.drawCircle(thumbCenter, 5.0, thumbPaint); context.canvas.drawCircle(thumbCenter, 5.0, thumbPaint);
......
...@@ -104,11 +104,13 @@ void main() { ...@@ -104,11 +104,13 @@ void main() {
const Color customColor1 = const Color(0xcafefeed); const Color customColor1 = const Color(0xcafefeed);
const Color customColor2 = const Color(0xdeadbeef); const Color customColor2 = const Color(0xdeadbeef);
const Color customColor3 = const Color(0xdecaface); const Color customColor3 = const Color(0xdecaface);
const Color customColor4 = const Color(0xfeedcafe);
final SliderThemeData sliderTheme = new SliderThemeData.fromPrimaryColors( final SliderThemeData sliderTheme = new SliderThemeData.fromPrimaryColors(
primaryColor: customColor1, primaryColor: customColor1,
primaryColorDark: customColor2, primaryColorDark: customColor2,
primaryColorLight: customColor3, primaryColorLight: customColor3,
valueIndicatorTextStyle: new ThemeData.fallback().accentTextTheme.body2.copyWith(color: customColor4),
); );
expect(sliderTheme.activeRailColor, equals(customColor1.withAlpha(0xff))); expect(sliderTheme.activeRailColor, equals(customColor1.withAlpha(0xff)));
...@@ -126,6 +128,7 @@ void main() { ...@@ -126,6 +128,7 @@ void main() {
expect(sliderTheme.thumbShape, equals(const isInstanceOf<RoundSliderThumbShape>())); expect(sliderTheme.thumbShape, equals(const isInstanceOf<RoundSliderThumbShape>()));
expect(sliderTheme.valueIndicatorShape, equals(const isInstanceOf<PaddleSliderValueIndicatorShape>())); expect(sliderTheme.valueIndicatorShape, equals(const isInstanceOf<PaddleSliderValueIndicatorShape>()));
expect(sliderTheme.showValueIndicator, equals(ShowValueIndicator.onlyForDiscrete)); expect(sliderTheme.showValueIndicator, equals(ShowValueIndicator.onlyForDiscrete));
expect(sliderTheme.valueIndicatorTextStyle.color, equals(customColor4));
}); });
testWidgets('SliderThemeData lerps correctly', (WidgetTester tester) async { testWidgets('SliderThemeData lerps correctly', (WidgetTester tester) async {
...@@ -133,11 +136,13 @@ void main() { ...@@ -133,11 +136,13 @@ void main() {
primaryColor: Colors.black, primaryColor: Colors.black,
primaryColorDark: Colors.black, primaryColorDark: Colors.black,
primaryColorLight: Colors.black, primaryColorLight: Colors.black,
valueIndicatorTextStyle: new ThemeData.fallback().accentTextTheme.body2.copyWith(color: Colors.black),
); );
final SliderThemeData sliderThemeWhite = new SliderThemeData.fromPrimaryColors( final SliderThemeData sliderThemeWhite = new SliderThemeData.fromPrimaryColors(
primaryColor: Colors.white, primaryColor: Colors.white,
primaryColorDark: Colors.white, primaryColorDark: Colors.white,
primaryColorLight: Colors.white, primaryColorLight: Colors.white,
valueIndicatorTextStyle: new ThemeData.fallback().accentTextTheme.body2.copyWith(color: Colors.white),
); );
final SliderThemeData lerp = SliderThemeData.lerp(sliderThemeBlack, sliderThemeWhite, 0.5); final SliderThemeData lerp = SliderThemeData.lerp(sliderThemeBlack, sliderThemeWhite, 0.5);
const Color middleGrey = const Color(0xff7f7f7f); const Color middleGrey = const Color(0xff7f7f7f);
...@@ -153,6 +158,7 @@ void main() { ...@@ -153,6 +158,7 @@ void main() {
expect(lerp.disabledThumbColor, equals(middleGrey.withAlpha(0x52))); expect(lerp.disabledThumbColor, equals(middleGrey.withAlpha(0x52)));
expect(lerp.overlayColor, equals(middleGrey.withAlpha(0x29))); 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)));
}); });
testWidgets('Default slider thumb shape draws correctly', (WidgetTester tester) async { testWidgets('Default slider thumb shape draws correctly', (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment