Add slider customizations (#11185)
* adds inactiveColor and showThumb to Slider * add customizable color and showThumb tests * remove showThumb, add negative tests
This commit is contained in:
parent
56700930a5
commit
bb15e346bb
@ -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 {
|
|||||||
/// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
..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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
_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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double computeMinIntrinsicWidth(double height) {
|
double computeMinIntrinsicWidth(double height) {
|
||||||
return _kMinimumTotalWidth;
|
return _kMinimumTotalWidth;
|
||||||
@ -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() {
|
|||||||
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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user