[Material] Allow slider shapes to be easily resized (#27510)
* Add size configs for round default shapes, and add tests, for all shapes that can be sized without creating new custom shape painters
This commit is contained in:
parent
3dbec84052
commit
b356b94aef
@ -601,7 +601,7 @@ class _RenderSlider extends RenderBox {
|
||||
_sliderTheme.thumbShape.getPreferredSize(isInteractive, isDiscrete),
|
||||
_sliderTheme.tickMarkShape.getPreferredSize(isEnabled: isInteractive, sliderTheme: sliderTheme),
|
||||
];
|
||||
double get _minPreferredTrackHeight =>_sliderTheme.trackHeight;
|
||||
double get _minPreferredTrackHeight => _sliderTheme.trackHeight;
|
||||
|
||||
_SliderState _state;
|
||||
Animation<double> _overlayAnimation;
|
||||
|
@ -846,9 +846,16 @@ abstract class SliderComponentShape {
|
||||
/// * [SliderTrackShape] Base component for creating other custom track
|
||||
/// shapes.
|
||||
class RectangularSliderTrackShape extends SliderTrackShape {
|
||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const RectangularSliderTrackShape();
|
||||
/// Create a slider track that draws 2 rectangles.
|
||||
const RectangularSliderTrackShape({ this.disabledThumbGapWidth = 2.0 });
|
||||
|
||||
/// Horizontal spacing, or gap, between the disabled thumb and the track.
|
||||
///
|
||||
/// This is only used when the slider is disabled. There is no gap around
|
||||
/// the thumb and any part of the track when the slider is enabled. The
|
||||
/// Material spec defaults this gap width 2, which is half of the disabled
|
||||
/// thumb radius.
|
||||
final double disabledThumbGapWidth;
|
||||
|
||||
@override
|
||||
Rect getPreferredRect({
|
||||
@ -874,8 +881,6 @@ class RectangularSliderTrackShape extends SliderTrackShape {
|
||||
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
|
||||
}
|
||||
|
||||
// Spacing for disabled slider state.
|
||||
static const double _thumbGap = 2.0;
|
||||
|
||||
@override
|
||||
void paint(
|
||||
@ -909,11 +914,15 @@ class RectangularSliderTrackShape extends SliderTrackShape {
|
||||
}
|
||||
|
||||
// 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 thumbRadius = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete).width / 2.0;
|
||||
final double gap = _thumbGap * (1.0 - enableAnimation.value);
|
||||
horizontalAdjustment = thumbRadius + gap;
|
||||
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(
|
||||
@ -949,16 +958,22 @@ class RectangularSliderTrackShape extends SliderTrackShape {
|
||||
/// * [SliderTheme], which can be used to configure the tick mark shape of all
|
||||
/// sliders in a widget subtree.
|
||||
class RoundSliderTickMarkShape extends SliderTickMarkShape {
|
||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const RoundSliderTickMarkShape();
|
||||
/// Create a slider tick mark that draws a circle.
|
||||
const RoundSliderTickMarkShape({ this.tickMarkRadius });
|
||||
|
||||
/// The preferred radius of the round tick mark.
|
||||
///
|
||||
/// If it is not provided, then half of the track height is used.
|
||||
final double tickMarkRadius;
|
||||
|
||||
@override
|
||||
Size getPreferredSize({
|
||||
bool isEnabled,
|
||||
SliderThemeData sliderTheme,
|
||||
}) {
|
||||
return Size.fromRadius(sliderTheme.trackHeight / 2);
|
||||
// The tick marks are tiny circles. If no radius is provided, then they are
|
||||
// defaulted to be the same height as the track.
|
||||
return Size.fromRadius(tickMarkRadius ?? sliderTheme.trackHeight / 2);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -991,7 +1006,10 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape {
|
||||
final Paint paint = Paint()..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation);
|
||||
|
||||
// The tick marks are tiny circles that are the same height as the track.
|
||||
final double tickMarkRadius = sliderTheme.trackHeight / 2;
|
||||
final double tickMarkRadius = getPreferredSize(
|
||||
isEnabled: isEnabled,
|
||||
sliderTheme: sliderTheme,
|
||||
).width / 2;
|
||||
context.canvas.drawCircle(center, tickMarkRadius, paint);
|
||||
}
|
||||
}
|
||||
@ -1005,14 +1023,30 @@ class RoundSliderTickMarkShape extends SliderTickMarkShape {
|
||||
/// sliders in a widget subtree.
|
||||
class RoundSliderThumbShape extends SliderComponentShape {
|
||||
/// Create a slider thumb that draws a circle.
|
||||
const RoundSliderThumbShape();
|
||||
// TODO(clocksmith): This needs to be changed to 10 according to spec.
|
||||
const RoundSliderThumbShape({
|
||||
this.enabledThumbRadius = 6.0,
|
||||
this.disabledThumbRadius
|
||||
});
|
||||
|
||||
static const double _thumbRadius = 6.0;
|
||||
static const double _disabledThumbRadius = 4.0;
|
||||
/// The preferred radius of the round thumb shape when the slider is enabled.
|
||||
///
|
||||
/// If it is not provided, then the material default is used.
|
||||
final double enabledThumbRadius;
|
||||
|
||||
/// The preferred radius of the round thumb shape when the slider is disabled.
|
||||
///
|
||||
/// If no disabledRadius is provided, then it is is derived from the enabled
|
||||
/// 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;
|
||||
// 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
|
||||
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
|
||||
return Size.fromRadius(isEnabled ? _thumbRadius : _disabledThumbRadius);
|
||||
return Size.fromRadius(isEnabled ? enabledThumbRadius : _disabledThumbRadius);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1031,7 +1065,7 @@ class RoundSliderThumbShape extends SliderComponentShape {
|
||||
final Canvas canvas = context.canvas;
|
||||
final Tween<double> radiusTween = Tween<double>(
|
||||
begin: _disabledThumbRadius,
|
||||
end: _thumbRadius,
|
||||
end: enabledThumbRadius,
|
||||
);
|
||||
final ColorTween colorTween = ColorTween(
|
||||
begin: sliderTheme.disabledThumbColor,
|
||||
@ -1062,13 +1096,17 @@ class RoundSliderThumbShape extends SliderComponentShape {
|
||||
/// sliders in a widget subtree.
|
||||
class RoundSliderOverlayShape extends SliderComponentShape {
|
||||
/// Create a slider thumb overlay that draws a circle.
|
||||
const RoundSliderOverlayShape();
|
||||
// TODO(clocksmith): This needs to be changed to 24 according to spec.
|
||||
const RoundSliderOverlayShape({ this.overlayRadius = 16.0 });
|
||||
|
||||
static const double _overlayRadius = 16.0;
|
||||
/// The preferred radius of the round thumb shape when enabled.
|
||||
///
|
||||
/// If it is not provided, then half of the track height is used.
|
||||
final double overlayRadius;
|
||||
|
||||
@override
|
||||
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
|
||||
return const Size.fromRadius(_overlayRadius);
|
||||
return Size.fromRadius(overlayRadius);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1087,7 +1125,7 @@ class RoundSliderOverlayShape extends SliderComponentShape {
|
||||
final Canvas canvas = context.canvas;
|
||||
final Tween<double> radiusTween = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: _overlayRadius,
|
||||
end: overlayRadius,
|
||||
);
|
||||
|
||||
// TODO(gspencer): We don't really follow the spec here for overlays.
|
||||
|
@ -30,32 +30,15 @@ void main() {
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme;
|
||||
|
||||
Widget buildSlider(SliderThemeData data) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData.fromWindow(window),
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: Theme(
|
||||
data: theme,
|
||||
child: const Slider(
|
||||
value: 0.5,
|
||||
label: '0.5',
|
||||
onChanged: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSlider(sliderTheme));
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, enabled: false));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(sliderBox, paints..rect(color: sliderTheme.disabledActiveTrackColor)..rect(color: sliderTheme.disabledInactiveTrackColor));
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..rect(color: sliderTheme.disabledActiveTrackColor)
|
||||
..rect(color: sliderTheme.disabledInactiveTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Slider overrides ThemeData theme if SliderTheme present', (WidgetTester tester) async {
|
||||
@ -69,35 +52,15 @@ void main() {
|
||||
inactiveTrackColor: Colors.purple.withAlpha(0x3d),
|
||||
);
|
||||
|
||||
Widget buildSlider(SliderThemeData data) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData.fromWindow(window),
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: Theme(
|
||||
data: theme,
|
||||
child: SliderTheme(
|
||||
data: customTheme,
|
||||
child: const Slider(
|
||||
value: 0.5,
|
||||
label: '0.5',
|
||||
onChanged: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSlider(sliderTheme));
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, enabled: false));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(sliderBox, paints..rect(color: customTheme.disabledActiveTrackColor)..rect(color: customTheme.disabledInactiveTrackColor));
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..rect(color: customTheme.disabledActiveTrackColor)
|
||||
..rect(color: customTheme.disabledInactiveTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SliderThemeData assigns the correct default shapes', (WidgetTester tester) async {
|
||||
@ -180,33 +143,12 @@ void main() {
|
||||
primarySwatch: Colors.blue,
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||
double value = 0.25;
|
||||
Widget buildApp({ bool enabled = true }) {
|
||||
final ValueChanged<double> onChanged = enabled ? (double d) => value = d : null;
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData.fromWindow(window),
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: SliderTheme(
|
||||
data: sliderTheme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
label: '$value',
|
||||
onChanged: onChanged,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildApp());
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
// The enabled slider thumb has track segments that extend to and from
|
||||
// the center of the thumb.
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
@ -214,10 +156,15 @@ void main() {
|
||||
..rect(rect: Rect.fromLTRB(208.0, 299.0, 784.0, 301.0), color: sliderTheme.inactiveTrackColor)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildApp(enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
// The disabled thumb is smaller so the track has to paint longer to get
|
||||
// to the edge.
|
||||
|
||||
// The disabled slider thumb has a horizontal gap between itself and the
|
||||
// track segments. Therefore, the track segments are shorter since they do
|
||||
// not extend to the center of the thumb, but rather the outer edge of th
|
||||
// gap. As a result, the `right` value of the first segment is less than it
|
||||
// is above, and the `left` value of the second segment is more than it is
|
||||
// above.
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
@ -232,31 +179,8 @@ void main() {
|
||||
primarySwatch: Colors.blue,
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||
double value = 0.25;
|
||||
Widget buildApp({ bool enabled = true }) {
|
||||
final ValueChanged<double> onChanged = enabled ? (double d) => value = d : null;
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData.fromWindow(window),
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: SliderTheme(
|
||||
data: sliderTheme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
label: '$value',
|
||||
onChanged: onChanged,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildApp());
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
// With no touch, paints only the thumb.
|
||||
@ -296,6 +220,7 @@ void main() {
|
||||
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// After the gesture is up and complete, it again paints only the thumb.
|
||||
expect(
|
||||
sliderBox,
|
||||
@ -315,45 +240,20 @@ void main() {
|
||||
primarySwatch: Colors.blue,
|
||||
);
|
||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||
double value = 0.45;
|
||||
Widget buildApp({
|
||||
int divisions,
|
||||
bool enabled = true,
|
||||
}) {
|
||||
final ValueChanged<double> onChanged = enabled ? (double d) => value = d : null;
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData.fromWindow(window),
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: SliderTheme(
|
||||
data: sliderTheme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
label: '$value',
|
||||
divisions: divisions,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildApp());
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(sliderBox, paints..circle(color: sliderTheme.thumbColor, radius: 6.0));
|
||||
|
||||
await tester.pumpWidget(buildApp(enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, enabled: false));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
|
||||
expect(sliderBox, paints..circle(color: sliderTheme.disabledThumbColor, radius: 4.0));
|
||||
|
||||
await tester.pumpWidget(buildApp(divisions: 3));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3));
|
||||
await tester.pumpAndSettle(); // wait for enable animation
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
@ -364,8 +264,9 @@ void main() {
|
||||
..circle(color: sliderTheme.thumbColor, radius: 6.0)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildApp(divisions: 3, enabled: false));
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45, divisions: 3, enabled: false));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
@ -548,4 +449,169 @@ void main() {
|
||||
);
|
||||
await gesture.up();
|
||||
});
|
||||
|
||||
testWidgets('The slider track height can be overridden', (WidgetTester tester) async {
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(trackHeight: 16);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
// Top and bottom are centerY (300) + and - trackRadius (8).
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..rect(rect: Rect.fromLTRB(16.0, 292.0, 208.0, 308.0), color: sliderTheme.activeTrackColor)
|
||||
..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.pumpAndSettle(); // wait for disable animation
|
||||
|
||||
// The disabled thumb is smaller so the active track has to paint longer to
|
||||
// get to the edge.
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..rect(rect: Rect.fromLTRB(16.0, 292.0, 202.0, 308.0), color: sliderTheme.disabledActiveTrackColor)
|
||||
..rect(rect: Rect.fromLTRB(214.0, 292.0, 784.0, 308.0), color: sliderTheme.disabledInactiveTrackColor)
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('The default slider thumb shape sizes can be overridden', (WidgetTester tester) async {
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
|
||||
thumbShape: const RoundSliderThumbShape(
|
||||
enabledThumbRadius: 7,
|
||||
disabledThumbRadius: 11,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints..circle(x: 208, y: 300, radius: 7, color: sliderTheme.thumbColor)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
|
||||
await tester.pumpAndSettle(); // wait for disable animation
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints..circle(x: 208, y: 300, radius: 11, color: sliderTheme.disabledThumbColor)
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('The default slider thumb shape disabled size can be inferred from the enabled size', (WidgetTester tester) async {
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
|
||||
thumbShape: const RoundSliderThumbShape(
|
||||
enabledThumbRadius: 9,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints..circle(x: 208, y: 300, radius: 9, color: sliderTheme.thumbColor)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, enabled: false));
|
||||
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(
|
||||
sliderBox,
|
||||
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 {
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
|
||||
tickMarkShape: const RoundSliderTickMarkShape(
|
||||
tickMarkRadius: 5
|
||||
),
|
||||
activeTickMarkColor: const Color(0xfadedead),
|
||||
inactiveTickMarkColor: const Color(0xfadebeef),
|
||||
disabledActiveTickMarkColor: const Color(0xfadecafe),
|
||||
disabledInactiveTickMarkColor: const Color(0xfadeface),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2));
|
||||
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..circle(x: 21, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor)
|
||||
..circle(x: 400, y: 300, radius: 5, color: sliderTheme.activeTickMarkColor)
|
||||
..circle(x: 779, y: 300, radius: 5, color: sliderTheme.inactiveTickMarkColor)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2, enabled: false));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
sliderBox,
|
||||
paints
|
||||
..circle(x: 21, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor)
|
||||
..circle(x: 400, y: 300, radius: 5, color: sliderTheme.disabledActiveTickMarkColor)
|
||||
..circle(x: 779, y: 300, radius: 5, color: sliderTheme.disabledInactiveTickMarkColor)
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('The default slider overlay shape size can be overridden', (WidgetTester tester) async {
|
||||
const double uniqueOverlayRadius = 23;
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
|
||||
overlayShape: const RoundSliderOverlayShape(
|
||||
overlayRadius: uniqueOverlayRadius,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5));
|
||||
// Tap center and wait for animation.
|
||||
final Offset center = tester.getCenter(find.byType(Slider));
|
||||
await tester.startGesture(center);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
|
||||
expect(
|
||||
sliderBox,
|
||||
paints..circle(
|
||||
x: center.dx,
|
||||
y: center.dy,
|
||||
radius: uniqueOverlayRadius,
|
||||
color: sliderTheme.overlayColor,
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildApp(
|
||||
SliderThemeData sliderTheme, {
|
||||
double value = 0.0,
|
||||
bool enabled = true,
|
||||
int divisions,
|
||||
}) {
|
||||
final ValueChanged<double> onChanged = enabled ? (double d) => value = d : null;
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: SliderTheme(
|
||||
data: sliderTheme,
|
||||
child: Slider(
|
||||
value: value,
|
||||
label: '$value',
|
||||
onChanged: onChanged,
|
||||
divisions: divisions,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user