Commit bb15e346 authored by Mary's avatar Mary Committed by Ian Hickson

Add slider customizations (#11185)

* adds inactiveColor and showThumb to Slider

* add customizable color and showThumb tests

* remove showThumb, add negative tests
parent 56700930
...@@ -64,6 +64,7 @@ class Slider extends StatefulWidget { ...@@ -64,6 +64,7 @@ class Slider extends StatefulWidget {
this.divisions, this.divisions,
this.label, this.label,
this.activeColor, this.activeColor,
this.inactiveColor,
this.thumbOpenAtMin: false, this.thumbOpenAtMin: false,
}) : assert(value != null), }) : assert(value != null),
assert(min != null), assert(min != null),
...@@ -138,6 +139,11 @@ class Slider extends StatefulWidget { ...@@ -138,6 +139,11 @@ class Slider extends StatefulWidget {
/// Defaults to accent color of the current [Theme]. /// Defaults to accent color of the current [Theme].
final Color activeColor; final Color activeColor;
/// The color for the unselected portion of the slider.
///
/// Defaults to the unselected widget color of the current [Theme].
final Color inactiveColor;
/// Whether the thumb should be an open circle when the slider is at its minimum position. /// Whether the thumb should be an open circle when the slider is at its minimum position.
/// ///
/// When this property is false, the thumb does not change when it the slider /// When this property is false, the thumb does not change when it the slider
...@@ -178,6 +184,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin { ...@@ -178,6 +184,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
divisions: widget.divisions, divisions: widget.divisions,
label: widget.label, label: widget.label,
activeColor: widget.activeColor ?? theme.accentColor, activeColor: widget.activeColor ?? theme.accentColor,
inactiveColor: widget.inactiveColor ?? theme.unselectedWidgetColor,
thumbOpenAtMin: widget.thumbOpenAtMin, thumbOpenAtMin: widget.thumbOpenAtMin,
textTheme: theme.accentTextTheme, textTheme: theme.accentTextTheme,
onChanged: (widget.onChanged != null) && (widget.max > widget.min) ? _handleChanged : null, onChanged: (widget.onChanged != null) && (widget.max > widget.min) ? _handleChanged : null,
...@@ -193,6 +200,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -193,6 +200,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
this.divisions, this.divisions,
this.label, this.label,
this.activeColor, this.activeColor,
this.inactiveColor,
this.thumbOpenAtMin, this.thumbOpenAtMin,
this.textTheme, this.textTheme,
this.onChanged, this.onChanged,
...@@ -203,6 +211,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -203,6 +211,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
final int divisions; final int divisions;
final String label; final String label;
final Color activeColor; final Color activeColor;
final Color inactiveColor;
final bool thumbOpenAtMin; final bool thumbOpenAtMin;
final TextTheme textTheme; final TextTheme textTheme;
final ValueChanged<double> onChanged; final ValueChanged<double> onChanged;
...@@ -215,6 +224,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -215,6 +224,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
divisions: divisions, divisions: divisions,
label: label, label: label,
activeColor: activeColor, activeColor: activeColor,
inactiveColor: inactiveColor,
thumbOpenAtMin: thumbOpenAtMin, thumbOpenAtMin: thumbOpenAtMin,
textTheme: textTheme, textTheme: textTheme,
onChanged: onChanged, onChanged: onChanged,
...@@ -229,6 +239,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -229,6 +239,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
..divisions = divisions ..divisions = divisions
..label = label ..label = label
..activeColor = activeColor ..activeColor = activeColor
..inactiveColor = inactiveColor
..thumbOpenAtMin = thumbOpenAtMin ..thumbOpenAtMin = thumbOpenAtMin
..textTheme = textTheme ..textTheme = textTheme
..onChanged = onChanged; ..onChanged = onChanged;
...@@ -246,11 +257,9 @@ const double _kMinimumTrackWidth = _kActiveThumbRadius; // biggest of the thumb ...@@ -246,11 +257,9 @@ const double _kMinimumTrackWidth = _kActiveThumbRadius; // biggest of the thumb
const double _kPreferredTotalWidth = _kPreferredTrackWidth + 2 * _kReactionRadius; const double _kPreferredTotalWidth = _kPreferredTrackWidth + 2 * _kReactionRadius;
const double _kMinimumTotalWidth = _kMinimumTrackWidth + 2 * _kReactionRadius; const double _kMinimumTotalWidth = _kMinimumTrackWidth + 2 * _kReactionRadius;
final Color _kInactiveTrackColor = Colors.grey.shade400;
final Color _kActiveTrackColor = Colors.grey; final Color _kActiveTrackColor = Colors.grey;
final Tween<double> _kReactionRadiusTween = new Tween<double>(begin: _kThumbRadius, end: _kReactionRadius); final Tween<double> _kReactionRadiusTween = new Tween<double>(begin: _kThumbRadius, end: _kReactionRadius);
final Tween<double> _kThumbRadiusTween = new Tween<double>(begin: _kThumbRadius, end: _kActiveThumbRadius); final Tween<double> _kThumbRadiusTween = new Tween<double>(begin: _kThumbRadius, end: _kActiveThumbRadius);
final ColorTween _kTrackColorTween = new ColorTween(begin: _kInactiveTrackColor, end: _kActiveTrackColor);
final ColorTween _kTickColorTween = new ColorTween(begin: Colors.transparent, end: Colors.black54); final ColorTween _kTickColorTween = new ColorTween(begin: Colors.transparent, end: Colors.black54);
final Duration _kDiscreteTransitionDuration = const Duration(milliseconds: 500); final Duration _kDiscreteTransitionDuration = const Duration(milliseconds: 500);
...@@ -276,6 +285,7 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler { ...@@ -276,6 +285,7 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler {
int divisions, int divisions,
String label, String label,
Color activeColor, Color activeColor,
Color inactiveColor,
bool thumbOpenAtMin, bool thumbOpenAtMin,
TextTheme textTheme, TextTheme textTheme,
this.onChanged, this.onChanged,
...@@ -284,6 +294,7 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler { ...@@ -284,6 +294,7 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler {
_value = value, _value = value,
_divisions = divisions, _divisions = divisions,
_activeColor = activeColor, _activeColor = activeColor,
_inactiveColor = inactiveColor,
_thumbOpenAtMin = thumbOpenAtMin, _thumbOpenAtMin = thumbOpenAtMin,
_textTheme = textTheme { _textTheme = textTheme {
this.label = label; this.label = label;
...@@ -363,6 +374,15 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler { ...@@ -363,6 +374,15 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler {
markNeedsPaint(); markNeedsPaint();
} }
Color get inactiveColor => _inactiveColor;
Color _inactiveColor;
set inactiveColor(Color value) {
if (value == _inactiveColor)
return;
_inactiveColor = value;
markNeedsPaint();
}
bool get thumbOpenAtMin => _thumbOpenAtMin; bool get thumbOpenAtMin => _thumbOpenAtMin;
bool _thumbOpenAtMin; bool _thumbOpenAtMin;
set thumbOpenAtMin(bool value) { set thumbOpenAtMin(bool value) {
...@@ -451,7 +471,6 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler { ...@@ -451,7 +471,6 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler {
} }
} }
@override @override
double computeMinIntrinsicWidth(double height) { double computeMinIntrinsicWidth(double height) {
return _kMinimumTotalWidth; return _kMinimumTotalWidth;
...@@ -501,8 +520,8 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler { ...@@ -501,8 +520,8 @@ class _RenderSlider extends RenderBox implements SemanticsActionHandler {
final double trackRight = trackLeft + trackLength; final double trackRight = trackLeft + trackLength;
final double trackActive = trackLeft + trackLength * value; final double trackActive = trackLeft + trackLength * value;
final Paint primaryPaint = new Paint()..color = enabled ? _activeColor : _kInactiveTrackColor; final Paint primaryPaint = new Paint()..color = enabled ? _activeColor : _inactiveColor;
final Paint trackPaint = new Paint()..color = _kTrackColorTween.evaluate(_reaction); final Paint trackPaint = new Paint()..color = _inactiveColor;
final Offset thumbCenter = new Offset(trackActive, trackCenter); final Offset thumbCenter = new Offset(trackActive, trackCenter);
final double thumbRadius = enabled ? _kThumbRadiusTween.evaluate(_reaction) : _kDisabledThumbRadius; final double thumbRadius = enabled ? _kThumbRadiusTween.evaluate(_reaction) : _kDisabledThumbRadius;
......
...@@ -118,6 +118,72 @@ void main() { ...@@ -118,6 +118,72 @@ void main() {
log.clear(); log.clear();
}); });
testWidgets('Slider has a customizable active color',
(WidgetTester tester) async {
final Color customColor = const Color(0xFF4CD964);
final ThemeData theme = new ThemeData(platform: TargetPlatform.android);
Widget buildApp(Color activeColor) {
return new Material(
child: new Center(
child: new Theme(
data: theme,
child: new Slider(
value: 0.5,
activeColor: activeColor,
onChanged: (double newValue) {},
),
),
),
);
}
await tester.pumpWidget(buildApp(null));
final RenderBox sliderBox =
tester.firstRenderObject<RenderBox>(find.byType(Slider));
expect(sliderBox, paints..rect(color: theme.accentColor)..rect(color: theme.unselectedWidgetColor));
expect(sliderBox, paints..circle(color: theme.accentColor));
expect(sliderBox, isNot(paints..circle(color: customColor)));
expect(sliderBox, isNot(paints..circle(color: theme.unselectedWidgetColor)));
await tester.pumpWidget(buildApp(customColor));
expect(sliderBox, paints..rect(color: customColor)..rect(color: theme.unselectedWidgetColor));
expect(sliderBox, paints..circle(color: customColor));
expect(sliderBox, isNot(paints..circle(color: theme.accentColor)));
expect(sliderBox, isNot(paints..circle(color: theme.unselectedWidgetColor)));
});
testWidgets('Slider has a customizable inactive color',
(WidgetTester tester) async {
final Color customColor = const Color(0xFF4CD964);
final ThemeData theme = new ThemeData(platform: TargetPlatform.android);
Widget buildApp(Color inactiveColor) {
return new Material(
child: new Center(
child: new Theme(
data: theme,
child: new Slider(
value: 0.5,
inactiveColor: inactiveColor,
onChanged: (double newValue) {},
),
),
),
);
}
await tester.pumpWidget(buildApp(null));
final RenderBox sliderBox =
tester.firstRenderObject<RenderBox>(find.byType(Slider));
expect(sliderBox, paints..rect(color: theme.accentColor)..rect(color: theme.unselectedWidgetColor));
expect(sliderBox, paints..circle(color: theme.accentColor));
await tester.pumpWidget(buildApp(customColor));
expect(sliderBox, paints..rect(color: theme.accentColor)..rect(color: customColor));
expect(sliderBox, paints..circle(color: theme.accentColor));
});
testWidgets('Slider can draw an open thumb at min', testWidgets('Slider can draw an open thumb at min',
(WidgetTester tester) async { (WidgetTester tester) async {
Widget buildApp(bool thumbOpenAtMin) { Widget buildApp(bool thumbOpenAtMin) {
......
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