Unverified Commit 0d3d8d4b authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] respect debugDisableShadows in slider thumbs (#105467)

parent 9f735613
...@@ -2366,7 +2366,19 @@ class RoundSliderThumbShape extends SliderComponentShape { ...@@ -2366,7 +2366,19 @@ class RoundSliderThumbShape extends SliderComponentShape {
final double evaluatedElevation = elevationTween.evaluate(activationAnimation); final double evaluatedElevation = elevationTween.evaluate(activationAnimation);
final Path path = Path() final Path path = Path()
..addArc(Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius), 0, math.pi * 2); ..addArc(Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius), 0, math.pi * 2);
canvas.drawShadow(path, Colors.black, evaluatedElevation, true);
bool paintShadows = true;
assert(() {
if (debugDisableShadows) {
_debugDrawShadow(canvas, path, evaluatedElevation);
paintShadows = false;
}
return true;
}());
if (paintShadows) {
canvas.drawShadow(path, Colors.black, evaluatedElevation, true);
}
canvas.drawCircle( canvas.drawCircle(
center, center,
...@@ -2475,7 +2487,19 @@ class RoundRangeSliderThumbShape extends RangeSliderThumbShape { ...@@ -2475,7 +2487,19 @@ class RoundRangeSliderThumbShape extends RangeSliderThumbShape {
final double evaluatedElevation = isPressed! ? elevationTween.evaluate(activationAnimation) : elevation; final double evaluatedElevation = isPressed! ? elevationTween.evaluate(activationAnimation) : elevation;
final Path shadowPath = Path() final Path shadowPath = Path()
..addArc(Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius), 0, math.pi * 2); ..addArc(Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius), 0, math.pi * 2);
canvas.drawShadow(shadowPath, Colors.black, evaluatedElevation, true);
bool paintShadows = true;
assert(() {
if (debugDisableShadows) {
_debugDrawShadow(canvas, shadowPath, evaluatedElevation);
paintShadows = false;
}
return true;
}());
if (paintShadows) {
canvas.drawShadow(shadowPath, Colors.black, evaluatedElevation, true);
}
canvas.drawCircle( canvas.drawCircle(
center, center,
...@@ -3359,3 +3383,15 @@ class RangeLabels { ...@@ -3359,3 +3383,15 @@ class RangeLabels {
return '${objectRuntimeType(this, 'RangeLabels')}($start, $end)'; return '${objectRuntimeType(this, 'RangeLabels')}($start, $end)';
} }
} }
void _debugDrawShadow(Canvas canvas, Path path, double elevation) {
if (elevation > 0.0) {
canvas.drawPath(
path,
Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = elevation * 2.0,
);
}
}
...@@ -1276,8 +1276,10 @@ void main() { ...@@ -1276,8 +1276,10 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..path(color: Colors.black) // shadow
..path(color: Colors.black) // shadow
..path(color: sliderTheme.valueIndicatorColor) ..path(color: sliderTheme.valueIndicatorColor)
..paragraph(), ..paragraph()
); );
await gesture.up(); await gesture.up();
// Wait for value indicator animation to finish. // Wait for value indicator animation to finish.
...@@ -1360,7 +1362,7 @@ void main() { ...@@ -1360,7 +1362,7 @@ void main() {
); );
// Represents the Raised Button and Range Slider. // Represents the Raised Button and Range Slider.
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 4)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 6));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3));
await tester.tap(find.text('Next')); await tester.tap(find.text('Next'));
...@@ -1370,11 +1372,11 @@ void main() { ...@@ -1370,11 +1372,11 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
isNot( isNot(
paints paints
..path(color: fillColor) ..path(color: fillColor)
..paragraph() ..paragraph()
..path(color: fillColor) ..path(color: fillColor)
..paragraph(), ..paragraph(),
), ),
); );
...@@ -1519,6 +1521,8 @@ void main() { ...@@ -1519,6 +1521,8 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..path(color: Colors.black) // shadow
..path(color: Colors.black) // shadow
..path(color: sliderTheme.valueIndicatorColor) ..path(color: sliderTheme.valueIndicatorColor)
..paragraph(), ..paragraph(),
); );
...@@ -1594,6 +1598,8 @@ void main() { ...@@ -1594,6 +1598,8 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..path(color: Colors.black) // shadow
..path(color: Colors.black) // shadow
..path(color: sliderTheme.valueIndicatorColor) ..path(color: sliderTheme.valueIndicatorColor)
..paragraph(), ..paragraph(),
); );
......
...@@ -627,217 +627,222 @@ void main() { ...@@ -627,217 +627,222 @@ void main() {
}); });
testWidgets('Slider uses the right theme colors for the right components', (WidgetTester tester) async { testWidgets('Slider uses the right theme colors for the right components', (WidgetTester tester) async {
const Color customColor1 = Color(0xcafefeed); debugDisableShadows = false;
const Color customColor2 = Color(0xdeadbeef); try {
final ThemeData theme = ThemeData( const Color customColor1 = Color(0xcafefeed);
platform: TargetPlatform.android, const Color customColor2 = Color(0xdeadbeef);
primarySwatch: Colors.blue, final ThemeData theme = ThemeData(
sliderTheme: const SliderThemeData( platform: TargetPlatform.android,
disabledThumbColor: Color(0xff000001), primarySwatch: Colors.blue,
disabledActiveTickMarkColor: Color(0xff000002), sliderTheme: const SliderThemeData(
disabledActiveTrackColor: Color(0xff000003), disabledThumbColor: Color(0xff000001),
disabledInactiveTickMarkColor: Color(0xff000004), disabledActiveTickMarkColor: Color(0xff000002),
disabledInactiveTrackColor: Color(0xff000005), disabledActiveTrackColor: Color(0xff000003),
activeTrackColor: Color(0xff000006), disabledInactiveTickMarkColor: Color(0xff000004),
activeTickMarkColor: Color(0xff000007), disabledInactiveTrackColor: Color(0xff000005),
inactiveTrackColor: Color(0xff000008), activeTrackColor: Color(0xff000006),
inactiveTickMarkColor: Color(0xff000009), activeTickMarkColor: Color(0xff000007),
overlayColor: Color(0xff000010), inactiveTrackColor: Color(0xff000008),
thumbColor: Color(0xff000011), inactiveTickMarkColor: Color(0xff000009),
valueIndicatorColor: Color(0xff000012), overlayColor: Color(0xff000010),
), thumbColor: Color(0xff000011),
); valueIndicatorColor: Color(0xff000012),
final SliderThemeData sliderTheme = theme.sliderTheme; ),
double value = 0.45; );
Widget buildApp({ final SliderThemeData sliderTheme = theme.sliderTheme;
Color? activeColor, double value = 0.45;
Color? inactiveColor, Widget buildApp({
int? divisions, Color? activeColor,
bool enabled = true, Color? inactiveColor,
}) { int? divisions,
final ValueChanged<double>? onChanged = !enabled bool enabled = true,
? null }) {
: (double d) { final ValueChanged<double>? onChanged = !enabled
value = d; ? null
}; : (double d) {
return MaterialApp( value = d;
home: Directionality( };
textDirection: TextDirection.ltr, return MaterialApp(
child: Material( home: Directionality(
child: Center( textDirection: TextDirection.ltr,
child: Theme( child: Material(
data: theme, child: Center(
child: Slider( child: Theme(
value: value, data: theme,
label: '$value', child: Slider(
divisions: divisions, value: value,
activeColor: activeColor, label: '$value',
inactiveColor: inactiveColor, divisions: divisions,
onChanged: onChanged, activeColor: activeColor,
inactiveColor: inactiveColor,
onChanged: onChanged,
),
), ),
), ),
), ),
), ),
), );
); }
}
await tester.pumpWidget(buildApp()); await tester.pumpWidget(buildApp());
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!; final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay)); final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
// Check default theme for enabled widget.
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
expect(material, paints..shadow(color: const Color(0xff000000)));
expect(material, paints..circle(color: sliderTheme.thumbColor));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
// Test setting only the activeColor.
await tester.pumpWidget(buildApp(activeColor: customColor1));
expect(material, paints..rrect(color: customColor1)..rrect(color: sliderTheme.inactiveTrackColor));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: customColor1));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test setting only the inactiveColor.
await tester.pumpWidget(buildApp(inactiveColor: customColor1));
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: customColor1));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: sliderTheme.thumbColor));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test setting both activeColor and inactiveColor.
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2));
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: customColor1));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test colors for discrete slider.
await tester.pumpWidget(buildApp(divisions: 3));
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
expect(
material,
paints
..circle(color: sliderTheme.activeTickMarkColor)
..circle(color: sliderTheme.activeTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor)
..shadow(color: Colors.black)
..circle(color: sliderTheme.thumbColor),
);
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test colors for discrete slider with inactiveColor and activeColor set.
await tester.pumpWidget(buildApp(
activeColor: customColor1,
inactiveColor: customColor2,
divisions: 3,
));
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
expect(
material,
paints
..circle(color: customColor2)
..circle(color: customColor2)
..circle(color: customColor1)
..circle(color: customColor1)
..shadow(color: Colors.black)
..circle(color: customColor1),
);
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
// Test default theme for disabled widget.
await tester.pumpWidget(buildApp(enabled: false));
await tester.pumpAndSettle();
expect(
material,
paints
..rrect(color: sliderTheme.disabledActiveTrackColor)
..rrect(color: sliderTheme.disabledInactiveTrackColor),
);
expect(material, paints..shadow(color: Colors.black)..circle(color: sliderTheme.disabledThumbColor));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
// Test setting the activeColor and inactiveColor for disabled widget. // Check default theme for enabled widget.
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, enabled: false)); expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
expect( expect(material, paints..shadow(color: const Color(0xff000000)));
material, expect(material, paints..circle(color: sliderTheme.thumbColor));
paints expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
..rrect(color: sliderTheme.disabledActiveTrackColor) expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
..rrect(color: sliderTheme.disabledInactiveTrackColor), expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
); expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
expect(material, paints..circle(color: sliderTheme.disabledThumbColor)); expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor))); // Test setting only the activeColor.
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor))); await tester.pumpWidget(buildApp(activeColor: customColor1));
expect(material, paints..rrect(color: customColor1)..rrect(color: sliderTheme.inactiveTrackColor));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: customColor1));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test setting only the inactiveColor.
await tester.pumpWidget(buildApp(inactiveColor: customColor1));
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: customColor1));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: sliderTheme.thumbColor));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test setting both activeColor and inactiveColor.
await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2));
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
expect(material, paints..shadow(color: Colors.black));
expect(material, paints..circle(color: customColor1));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test colors for discrete slider.
await tester.pumpWidget(buildApp(divisions: 3));
expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
expect(
material,
paints
..circle(color: sliderTheme.activeTickMarkColor)
..circle(color: sliderTheme.activeTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor)
..circle(color: sliderTheme.inactiveTickMarkColor)
..shadow(color: Colors.black)
..circle(color: sliderTheme.thumbColor),
);
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
// Test colors for discrete slider with inactiveColor and activeColor set.
await tester.pumpWidget(buildApp(
activeColor: customColor1,
inactiveColor: customColor2,
divisions: 3,
));
expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
expect(
material,
paints
..circle(color: customColor2)
..circle(color: customColor2)
..circle(color: customColor1)
..circle(color: customColor1)
..shadow(color: Colors.black)
..circle(color: customColor1),
);
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
// Test default theme for disabled widget.
await tester.pumpWidget(buildApp(enabled: false));
await tester.pumpAndSettle();
expect(
material,
paints
..rrect(color: sliderTheme.disabledActiveTrackColor)
..rrect(color: sliderTheme.disabledInactiveTrackColor),
);
expect(material, paints..shadow(color: Colors.black)..circle(color: sliderTheme.disabledThumbColor));
expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
// Test that the default value indicator has the right colors. // Test setting the activeColor and inactiveColor for disabled widget.
await tester.pumpWidget(buildApp(divisions: 3)); await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, enabled: false));
Offset center = tester.getCenter(find.byType(Slider)); expect(
TestGesture gesture = await tester.startGesture(center); material,
// Wait for value indicator animation to finish. paints
await tester.pumpAndSettle(); ..rrect(color: sliderTheme.disabledActiveTrackColor)
expect(value, equals(2.0 / 3.0)); ..rrect(color: sliderTheme.disabledInactiveTrackColor),
expect( );
valueIndicatorBox, expect(material, paints..circle(color: sliderTheme.disabledThumbColor));
paints expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
..path(color: sliderTheme.valueIndicatorColor) expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
..paragraph(), expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));
);
await gesture.up(); // Test that the default value indicator has the right colors.
// Wait for value indicator animation to finish. await tester.pumpWidget(buildApp(divisions: 3));
await tester.pumpAndSettle(); Offset center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(value, equals(2.0 / 3.0));
expect(
valueIndicatorBox,
paints
..path(color: sliderTheme.valueIndicatorColor)
..paragraph(),
);
await gesture.up();
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
// Testing the custom colors are used for the indicator. // Testing the custom colors are used for the indicator.
await tester.pumpWidget(buildApp( await tester.pumpWidget(buildApp(
divisions: 3, divisions: 3,
activeColor: customColor1, activeColor: customColor1,
inactiveColor: customColor2, inactiveColor: customColor2,
)); ));
center = tester.getCenter(find.byType(Slider)); center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish. // Wait for value indicator animation to finish.
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(value, equals(2.0 / 3.0)); expect(value, equals(2.0 / 3.0));
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..rrect(color: const Color(0xfffafafa)) ..rrect(color: const Color(0xfffafafa))
..rrect(color: customColor1) // active track ..rrect(color: customColor1) // active track
..rrect(color: customColor2) // inactive track ..rrect(color: customColor2) // inactive track
..circle(color: customColor1.withOpacity(0.12)) // overlay ..circle(color: customColor1.withOpacity(0.12)) // 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
..circle(color: customColor1) // 4th tick mark ..circle(color: customColor1) // 4th tick mark
..shadow(color: Colors.black) ..shadow(color: Colors.black)
..circle(color: customColor1) // thumb ..circle(color: customColor1) // thumb
..path(color: sliderTheme.valueIndicatorColor), // indicator ..path(color: sliderTheme.valueIndicatorColor), // indicator
); );
await gesture.up(); await gesture.up();
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('Slider can tap in vertical scroller', (WidgetTester tester) async { testWidgets('Slider can tap in vertical scroller', (WidgetTester tester) async {
...@@ -1033,152 +1038,157 @@ void main() { ...@@ -1033,152 +1038,157 @@ void main() {
}); });
testWidgets('Slider respects textScaleFactor', (WidgetTester tester) async { testWidgets('Slider respects textScaleFactor', (WidgetTester tester) async {
final Key sliderKey = UniqueKey(); debugDisableShadows = false;
double value = 0.0; try {
final Key sliderKey = UniqueKey();
Widget buildSlider({ double value = 0.0;
required double textScaleFactor,
bool isDiscrete = true, Widget buildSlider({
ShowValueIndicator show = ShowValueIndicator.onlyForDiscrete, required double textScaleFactor,
}) { bool isDiscrete = true,
return MaterialApp( ShowValueIndicator show = ShowValueIndicator.onlyForDiscrete,
home: Directionality( }) {
textDirection: TextDirection.ltr, return MaterialApp(
child: StatefulBuilder( home: Directionality(
builder: (BuildContext context, StateSetter setState) { textDirection: TextDirection.ltr,
return MediaQuery( child: StatefulBuilder(
data: MediaQueryData(textScaleFactor: textScaleFactor), builder: (BuildContext context, StateSetter setState) {
child: Material( return MediaQuery(
child: Theme( data: MediaQueryData(textScaleFactor: textScaleFactor),
data: Theme.of(context).copyWith( child: Material(
sliderTheme: Theme.of(context).sliderTheme.copyWith(showValueIndicator: show), child: Theme(
), data: Theme.of(context).copyWith(
child: Center( sliderTheme: Theme.of(context).sliderTheme.copyWith(showValueIndicator: show),
child: OverflowBox( ),
maxWidth: double.infinity, child: Center(
maxHeight: double.infinity, child: OverflowBox(
child: Slider( maxWidth: double.infinity,
key: sliderKey, maxHeight: double.infinity,
max: 100.0, child: Slider(
divisions: isDiscrete ? 10 : null, key: sliderKey,
label: '${value.round()}', max: 100.0,
value: value, divisions: isDiscrete ? 10 : null,
onChanged: (double newValue) { label: '${value.round()}',
setState(() { value: value,
value = newValue; onChanged: (double newValue) {
}); setState(() {
}, value = newValue;
});
},
),
), ),
), ),
), ),
), ),
), );
); },
}, ),
), ),
), );
); }
}
await tester.pumpWidget(buildSlider(textScaleFactor: 1.0)); await tester.pumpWidget(buildSlider(textScaleFactor: 1.0));
Offset center = tester.getCenter(find.byType(Slider)); Offset center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center); TestGesture gesture = await tester.startGesture(center);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
tester.renderObject(find.byType(Overlay)), tester.renderObject(find.byType(Overlay)),
paints paints
..path( ..path(
includes: const <Offset>[ includes: const <Offset>[
Offset.zero, Offset.zero,
Offset(0.0, -8.0), Offset(0.0, -8.0),
Offset(-276.0, -16.0), Offset(-276.0, -16.0),
Offset(-216.0, -16.0), Offset(-216.0, -16.0),
], ],
color: const Color(0xf55f5f5f), color: const Color(0xf55f5f5f),
) )
..paragraph(), ..paragraph(),
); );
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.pumpWidget(buildSlider(textScaleFactor: 2.0)); await tester.pumpWidget(buildSlider(textScaleFactor: 2.0));
center = tester.getCenter(find.byType(Slider)); center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
tester.renderObject(find.byType(Overlay)), tester.renderObject(find.byType(Overlay)),
paints paints
..path( ..path(
includes: const <Offset>[ includes: const <Offset>[
Offset.zero, Offset.zero,
Offset(0.0, -8.0), Offset(0.0, -8.0),
Offset(-304.0, -16.0), Offset(-304.0, -16.0),
Offset(-216.0, -16.0), Offset(-216.0, -16.0),
], ],
color: const Color(0xf55f5f5f), color: const Color(0xf55f5f5f),
) )
..paragraph(), ..paragraph(),
); );
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// Check continuous // Check continuous
await tester.pumpWidget(buildSlider( await tester.pumpWidget(buildSlider(
textScaleFactor: 1.0, textScaleFactor: 1.0,
isDiscrete: false, isDiscrete: false,
show: ShowValueIndicator.onlyForContinuous, show: ShowValueIndicator.onlyForContinuous,
)); ));
center = tester.getCenter(find.byType(Slider)); center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(tester.renderObject(find.byType(Overlay)), expect(tester.renderObject(find.byType(Overlay)),
paints paints
..path( ..path(
includes: const <Offset>[ includes: const <Offset>[
Offset.zero, Offset.zero,
Offset(0.0, -8.0), Offset(0.0, -8.0),
Offset(-276.0, -16.0), Offset(-276.0, -16.0),
Offset(-216.0, -16.0), Offset(-216.0, -16.0),
], ],
color: const Color(0xf55f5f5f), color: const Color(0xf55f5f5f),
) )
..paragraph(), ..paragraph(),
); );
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.pumpWidget(buildSlider( await tester.pumpWidget(buildSlider(
textScaleFactor: 2.0, textScaleFactor: 2.0,
isDiscrete: false, isDiscrete: false,
show: ShowValueIndicator.onlyForContinuous, show: ShowValueIndicator.onlyForContinuous,
)); ));
center = tester.getCenter(find.byType(Slider)); center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
tester.renderObject(find.byType(Overlay)), tester.renderObject(find.byType(Overlay)),
paints paints
..path( ..path(
includes: const <Offset>[ includes: const <Offset>[
Offset.zero, Offset.zero,
Offset(0.0, -8.0), Offset(0.0, -8.0),
Offset(-276.0, -16.0), Offset(-276.0, -16.0),
Offset(-216.0, -16.0), Offset(-216.0, -16.0),
], ],
color: const Color(0xf55f5f5f), color: const Color(0xf55f5f5f),
) )
..paragraph(), ..paragraph(),
); );
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('Tick marks are skipped when they are too dense', (WidgetTester tester) async { testWidgets('Tick marks are skipped when they are too dense', (WidgetTester tester) async {
...@@ -2552,7 +2562,7 @@ void main() { ...@@ -2552,7 +2562,7 @@ void main() {
..paragraph(), ..paragraph(),
); );
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 3)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 4));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2));
await tester.tap(find.text('Next')); await tester.tap(find.text('Next'));
......
...@@ -362,357 +362,367 @@ void main() { ...@@ -362,357 +362,367 @@ void main() {
}); });
testWidgets('Default paddle slider value indicator shape draws correctly', (WidgetTester tester) async { testWidgets('Default paddle slider value indicator shape draws correctly', (WidgetTester tester) async {
final ThemeData theme = ThemeData( debugDisableShadows = false;
platform: TargetPlatform.android, try {
primarySwatch: Colors.blue, final ThemeData theme = ThemeData(
); platform: TargetPlatform.android,
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith( primarySwatch: Colors.blue,
thumbColor: Colors.red.shade500, );
showValueIndicator: ShowValueIndicator.always, final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(
valueIndicatorShape: const PaddleSliderValueIndicatorShape(), thumbColor: Colors.red.shade500,
); showValueIndicator: ShowValueIndicator.always,
Widget buildApp(String value, { double sliderValue = 0.5, double textScale = 1.0 }) { valueIndicatorShape: const PaddleSliderValueIndicatorShape(),
return MaterialApp( );
home: Directionality( Widget buildApp(String value, { double sliderValue = 0.5, double textScale = 1.0 }) {
textDirection: TextDirection.ltr, return MaterialApp(
child: MediaQuery( home: Directionality(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScale), textDirection: TextDirection.ltr,
child: Material( child: MediaQuery(
child: Row( data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScale),
children: <Widget>[ child: Material(
Expanded( child: Row(
child: SliderTheme( children: <Widget>[
data: sliderTheme, Expanded(
child: Slider( child: SliderTheme(
value: sliderValue, data: sliderTheme,
label: value, child: Slider(
divisions: 3, value: sliderValue,
onChanged: (double d) { }, label: value,
divisions: 3,
onChanged: (double d) { },
),
), ),
), ),
), ],
], ),
), ),
), ),
), ),
), );
}
await tester.pumpWidget(buildApp('1'));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
Offset center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(15.9, -40.0),
const Offset(-15.9, -40.0),
],
excludes: <Offset>[const Offset(16.1, -40.0), const Offset(-16.1, -40.0)],
),
); );
}
await tester.pumpWidget(buildApp('1')); await gesture.up();
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay)); // Test that it expands with a larger label.
await tester.pumpWidget(buildApp('1000'));
Offset center = tester.getCenter(find.byType(Slider)); center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish. // Wait for value indicator animation to finish.
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..path( ..path(
color: sliderTheme.valueIndicatorColor, color: sliderTheme.valueIndicatorColor,
includes: <Offset>[ includes: <Offset>[
const Offset(0.0, -40.0), const Offset(0.0, -40.0),
const Offset(15.9, -40.0), const Offset(35.9, -40.0),
const Offset(-15.9, -40.0), const Offset(-35.9, -40.0),
], ],
excludes: <Offset>[const Offset(16.1, -40.0), const Offset(-16.1, -40.0)], excludes: <Offset>[const Offset(36.1, -40.0), const Offset(-36.1, -40.0)],
), ),
); );
await gesture.up();
await gesture.up();
// Test that it avoids the left edge of the screen.
// Test that it expands with a larger label. await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0));
await tester.pumpWidget(buildApp('1000')); center = tester.getCenter(find.byType(Slider));
center = tester.getCenter(find.byType(Slider)); gesture = await tester.startGesture(center);
gesture = await tester.startGesture(center); // Wait for value indicator animation to finish.
// Wait for value indicator animation to finish. await tester.pumpAndSettle();
await tester.pumpAndSettle(); expect(
expect( valueIndicatorBox,
valueIndicatorBox, paints
paints ..path(
..path( 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(35.9, -40.0), const Offset(-16.0, -40.0),
const Offset(-35.9, -40.0), ],
], excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-20.1, -40.0)],
excludes: <Offset>[const Offset(36.1, -40.0), const Offset(-36.1, -40.0)], ),
), );
); await gesture.up();
await gesture.up();
// Test that it avoids the right edge of the screen.
// Test that it avoids the left edge of the screen. await tester.pumpWidget(buildApp('1000000', sliderValue: 1.0));
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0)); center = tester.getCenter(find.byType(Slider));
center = tester.getCenter(find.byType(Slider)); gesture = await tester.startGesture(center);
gesture = await tester.startGesture(center); // Wait for value indicator animation to finish.
// Wait for value indicator animation to finish. await tester.pumpAndSettle();
await tester.pumpAndSettle(); expect(
expect( valueIndicatorBox,
valueIndicatorBox, paints
paints ..path(
..path( color: sliderTheme.valueIndicatorColor,
color: sliderTheme.valueIndicatorColor, includes: <Offset>[
includes: <Offset>[ const Offset(0.0, -40.0),
const Offset(0.0, -40.0), const Offset(16.0, -40.0),
const Offset(92.0, -40.0), const Offset(-92.0, -40.0),
const Offset(-16.0, -40.0), ],
], excludes: <Offset>[const Offset(20.1, -40.0), const Offset(-98.1, -40.0)],
excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-20.1, -40.0)], ),
), );
); await gesture.up();
await gesture.up();
// Test that the neck stretches when the text scale gets smaller.
// Test that it avoids the right edge of the screen. await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 0.5));
await tester.pumpWidget(buildApp('1000000', sliderValue: 1.0)); center = tester.getCenter(find.byType(Slider));
center = tester.getCenter(find.byType(Slider)); gesture = await tester.startGesture(center);
gesture = await tester.startGesture(center); // Wait for value indicator animation to finish.
// Wait for value indicator animation to finish. await tester.pumpAndSettle();
await tester.pumpAndSettle(); expect(
expect( valueIndicatorBox,
valueIndicatorBox, paints
paints ..path(
..path( color: sliderTheme.valueIndicatorColor,
color: sliderTheme.valueIndicatorColor, includes: <Offset>[
includes: <Offset>[ const Offset(0.0, -49.0),
const Offset(0.0, -40.0), const Offset(68.0, -49.0),
const Offset(16.0, -40.0), const Offset(-24.0, -49.0),
const Offset(-92.0, -40.0), ],
], excludes: <Offset>[
excludes: <Offset>[const Offset(20.1, -40.0), const Offset(-98.1, -40.0)], const Offset(98.0, -32.0), // inside full size, outside small
), const Offset(-40.0, -32.0), // inside full size, outside small
); const Offset(90.1, -49.0),
await gesture.up(); const Offset(-40.1, -49.0),
],
// Test that the neck stretches when the text scale gets smaller. ),
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 0.5)); );
center = tester.getCenter(find.byType(Slider)); await gesture.up();
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish. // Test that the neck shrinks when the text scale gets larger.
await tester.pumpAndSettle(); await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 2.5));
expect( center = tester.getCenter(find.byType(Slider));
valueIndicatorBox, gesture = await tester.startGesture(center);
paints // Wait for value indicator animation to finish.
..path( await tester.pumpAndSettle();
color: sliderTheme.valueIndicatorColor, expect(
includes: <Offset>[ valueIndicatorBox,
const Offset(0.0, -49.0), paints
const Offset(68.0, -49.0), ..path(
const Offset(-24.0, -49.0), color: sliderTheme.valueIndicatorColor,
], includes: <Offset>[
excludes: <Offset>[ const Offset(0.0, -38.8),
const Offset(98.0, -32.0), // inside full size, outside small const Offset(92.0, -38.8),
const Offset(-40.0, -32.0), // inside full size, outside small const Offset(8.0, -23.0), // Inside large, outside scale=1.0
const Offset(90.1, -49.0), const Offset(-2.0, -23.0), // Inside large, outside scale=1.0
const Offset(-40.1, -49.0), ],
], excludes: <Offset>[
), const Offset(98.5, -38.8),
); const Offset(-16.1, -38.8),
await gesture.up(); ],
),
// Test that the neck shrinks when the text scale gets larger. );
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 2.5)); await gesture.up();
center = tester.getCenter(find.byType(Slider)); } finally {
gesture = await tester.startGesture(center); debugDisableShadows = true;
// Wait for value indicator animation to finish. }
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -38.8),
const Offset(92.0, -38.8),
const Offset(8.0, -23.0), // Inside large, outside scale=1.0
const Offset(-2.0, -23.0), // Inside large, outside scale=1.0
],
excludes: <Offset>[
const Offset(98.5, -38.8),
const Offset(-16.1, -38.8),
],
),
);
await gesture.up();
}); });
testWidgets('Default paddle slider value indicator shape draws correctly', (WidgetTester tester) async { testWidgets('Default paddle slider value indicator shape draws correctly', (WidgetTester tester) async {
final ThemeData theme = ThemeData( debugDisableShadows = false;
platform: TargetPlatform.android, try {
primarySwatch: Colors.blue, final ThemeData theme = ThemeData(
); platform: TargetPlatform.android,
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith( primarySwatch: Colors.blue,
thumbColor: Colors.red.shade500, );
showValueIndicator: ShowValueIndicator.always, final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(
valueIndicatorShape: const PaddleSliderValueIndicatorShape(), thumbColor: Colors.red.shade500,
); showValueIndicator: ShowValueIndicator.always,
Widget buildApp(String value, { double sliderValue = 0.5, double textScale = 1.0 }) { valueIndicatorShape: const PaddleSliderValueIndicatorShape(),
return MaterialApp( );
home: Directionality( Widget buildApp(String value, { double sliderValue = 0.5, double textScale = 1.0 }) {
textDirection: TextDirection.ltr, return MaterialApp(
child: MediaQuery( home: Directionality(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScale), textDirection: TextDirection.ltr,
child: Material( child: MediaQuery(
child: Row( data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScale),
children: <Widget>[ child: Material(
Expanded( child: Row(
child: SliderTheme( children: <Widget>[
data: sliderTheme, Expanded(
child: Slider( child: SliderTheme(
value: sliderValue, data: sliderTheme,
label: value, child: Slider(
divisions: 3, value: sliderValue,
onChanged: (double d) { }, label: value,
divisions: 3,
onChanged: (double d) { },
),
), ),
), ),
), ],
], ),
), ),
), ),
), ),
), );
}
await tester.pumpWidget(buildApp('1'));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
Offset center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(15.9, -40.0),
const Offset(-15.9, -40.0),
],
excludes: <Offset>[const Offset(16.1, -40.0), const Offset(-16.1, -40.0)],
),
); );
}
await tester.pumpWidget(buildApp('1'));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
Offset center = tester.getCenter(find.byType(Slider));
TestGesture gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(15.9, -40.0),
const Offset(-15.9, -40.0),
],
excludes: <Offset>[const Offset(16.1, -40.0), const Offset(-16.1, -40.0)],
),
);
await gesture.up();
// Test that it expands with a larger label.
await tester.pumpWidget(buildApp('1000'));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(35.9, -40.0),
const Offset(-35.9, -40.0),
],
excludes: <Offset>[const Offset(36.1, -40.0), const Offset(-36.1, -40.0)],
),
);
await gesture.up();
// Test that it avoids the left edge of the screen.
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(92.0, -40.0),
const Offset(-16.0, -40.0),
],
excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-20.1, -40.0)],
),
);
await gesture.up();
// Test that it avoids the right edge of the screen.
await tester.pumpWidget(buildApp('1000000', sliderValue: 1.0));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(16.0, -40.0),
const Offset(-92.0, -40.0),
],
excludes: <Offset>[const Offset(20.1, -40.0), const Offset(-98.1, -40.0)],
),
);
await gesture.up();
// Test that the neck stretches when the text scale gets smaller.
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 0.5));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -49.0),
const Offset(68.0, -49.0),
const Offset(-24.0, -49.0),
],
excludes: <Offset>[
const Offset(98.0, -32.0), // inside full size, outside small
const Offset(-40.0, -32.0), // inside full size, outside small
const Offset(90.1, -49.0),
const Offset(-40.1, -49.0),
],
),
);
await gesture.up();
// Test that the neck shrinks when the text scale gets larger. await gesture.up();
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 2.5));
center = tester.getCenter(find.byType(Slider)); // Test that it expands with a larger label.
gesture = await tester.startGesture(center); await tester.pumpWidget(buildApp('1000'));
// Wait for value indicator animation to finish. center = tester.getCenter(find.byType(Slider));
await tester.pumpAndSettle(); gesture = await tester.startGesture(center);
expect( // Wait for value indicator animation to finish.
valueIndicatorBox, await tester.pumpAndSettle();
paints expect(
..path( valueIndicatorBox,
color: sliderTheme.valueIndicatorColor, paints
includes: <Offset>[ ..path(
const Offset(0.0, -38.8), color: sliderTheme.valueIndicatorColor,
const Offset(92.0, -38.8), includes: <Offset>[
const Offset(8.0, -23.0), // Inside large, outside scale=1.0 const Offset(0.0, -40.0),
const Offset(-2.0, -23.0), // Inside large, outside scale=1.0 const Offset(35.9, -40.0),
], const Offset(-35.9, -40.0),
excludes: <Offset>[ ],
const Offset(98.5, -38.8), excludes: <Offset>[const Offset(36.1, -40.0), const Offset(-36.1, -40.0)],
const Offset(-16.1, -38.8), ),
], );
), await gesture.up();
);
await gesture.up(); // Test that it avoids the left edge of the screen.
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(92.0, -40.0),
const Offset(-16.0, -40.0),
],
excludes: <Offset>[const Offset(98.1, -40.0), const Offset(-20.1, -40.0)],
),
);
await gesture.up();
// Test that it avoids the right edge of the screen.
await tester.pumpWidget(buildApp('1000000', sliderValue: 1.0));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -40.0),
const Offset(16.0, -40.0),
const Offset(-92.0, -40.0),
],
excludes: <Offset>[const Offset(20.1, -40.0), const Offset(-98.1, -40.0)],
),
);
await gesture.up();
// Test that the neck stretches when the text scale gets smaller.
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 0.5));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -49.0),
const Offset(68.0, -49.0),
const Offset(-24.0, -49.0),
],
excludes: <Offset>[
const Offset(98.0, -32.0), // inside full size, outside small
const Offset(-40.0, -32.0), // inside full size, outside small
const Offset(90.1, -49.0),
const Offset(-40.1, -49.0),
],
),
);
await gesture.up();
// Test that the neck shrinks when the text scale gets larger.
await tester.pumpWidget(buildApp('1000000', sliderValue: 0.0, textScale: 2.5));
center = tester.getCenter(find.byType(Slider));
gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
..path(
color: sliderTheme.valueIndicatorColor,
includes: <Offset>[
const Offset(0.0, -38.8),
const Offset(92.0, -38.8),
const Offset(8.0, -23.0), // Inside large, outside scale=1.0
const Offset(-2.0, -23.0), // Inside large, outside scale=1.0
],
excludes: <Offset>[
const Offset(98.5, -38.8),
const Offset(-16.1, -38.8),
],
),
);
await gesture.up();
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('The slider track height can be overridden', (WidgetTester tester) async { testWidgets('The slider track height can be overridden', (WidgetTester tester) async {
...@@ -967,24 +977,29 @@ void main() { ...@@ -967,24 +977,29 @@ void main() {
}); });
testWidgets('The slider can skip all component painting except the thumb', (WidgetTester tester) async { testWidgets('The slider can skip all component painting except the thumb', (WidgetTester tester) async {
// Pump a slider with just a thumb. debugDisableShadows = false;
await tester.pumpWidget(_buildApp( try {
ThemeData().sliderTheme.copyWith( // Pump a slider with just a thumb.
trackHeight: 0, await tester.pumpWidget(_buildApp(
overlayShape: SliderComponentShape.noOverlay, ThemeData().sliderTheme.copyWith(
tickMarkShape: SliderTickMarkShape.noTickMark, trackHeight: 0,
showValueIndicator: ShowValueIndicator.never, overlayShape: SliderComponentShape.noOverlay,
), tickMarkShape: SliderTickMarkShape.noTickMark,
value: 0.5, showValueIndicator: ShowValueIndicator.never,
divisions: 4, ),
)); value: 0.5,
divisions: 4,
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!; ));
// Only 1 thumb. final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
expect(material, paintsExactlyCountTimes(#drawRect, 0));
expect(material, paintsExactlyCountTimes(#drawCircle, 1)); // Only 1 thumb.
expect(material, paintsExactlyCountTimes(#drawPath, 0)); expect(material, paintsExactlyCountTimes(#drawRect, 0));
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
expect(material, paintsExactlyCountTimes(#drawPath, 0));
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('The slider can skip all component painting except the overlay', (WidgetTester tester) async { testWidgets('The slider can skip all component painting except the overlay', (WidgetTester tester) async {
...@@ -1113,6 +1128,57 @@ void main() { ...@@ -1113,6 +1128,57 @@ void main() {
testWidgets('Default paddle range slider value indicator shape draws correctly', (WidgetTester tester) async { testWidgets('Default paddle range slider value indicator shape draws correctly', (WidgetTester tester) async {
debugDisableShadows = false;
try {
final ThemeData theme = ThemeData(
platform: TargetPlatform.android,
primarySwatch: Colors.blue,
);
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(
thumbColor: Colors.red.shade500,
showValueIndicator: ShowValueIndicator.always,
rangeValueIndicatorShape: const PaddleRangeSliderValueIndicatorShape(),
);
await tester.pumpWidget(_buildRangeApp(sliderTheme));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
final Offset center = tester.getCenter(find.byType(RangeSlider));
final TestGesture gesture = await tester.startGesture(center);
// Wait for value indicator animation to finish.
await tester.pumpAndSettle();
expect(
valueIndicatorBox,
paints
// physical model
..rrect()
..rrect(rrect: RRect.fromLTRBAndCorners(
24.0, 298.0, 24.0, 302.0,
topLeft: const Radius.circular(2.0),
bottomLeft: const Radius.circular(2.0),
))
..rect(rect: const Rect.fromLTRB(24.0, 297.0, 24.0, 303.0))
..rrect(rrect: RRect.fromLTRBAndCorners(
24.0, 298.0, 776.0, 302.0,
topRight: const Radius.circular(2.0),
bottomRight: const Radius.circular(2.0),
))
..circle(x: 24.0, y: 300.0)
..shadow(elevation: 1.0)
..circle(x: 24.0, y: 300.0)
..shadow(elevation: 6.0)
..circle(x: 24.0, y: 300.0),
);
await gesture.up();
} finally {
debugDisableShadows = true;
}
});
testWidgets('Default paddle range slider value indicator shape draws correctly with debugDisableShadows', (WidgetTester tester) async {
debugDisableShadows = true;
final ThemeData theme = ThemeData( final ThemeData theme = ThemeData(
platform: TargetPlatform.android, platform: TargetPlatform.android,
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
...@@ -1148,74 +1214,83 @@ void main() { ...@@ -1148,74 +1214,83 @@ void main() {
bottomRight: const Radius.circular(2.0), bottomRight: const Radius.circular(2.0),
)) ))
..circle(x: 24.0, y: 300.0) ..circle(x: 24.0, y: 300.0)
..shadow(elevation: 1.0) ..path(strokeWidth: 1.0 * 2.0, color: Colors.black)
..circle(x: 24.0, y: 300.0) ..circle(x: 24.0, y: 300.0)
..shadow(elevation: 6.0) ..path(strokeWidth: 6.0 * 2.0, color: Colors.black)
..circle(x: 24.0, y: 300.0), ..circle(x: 24.0, y: 300.0),
); );
await gesture.up(); await gesture.up();
}); });
testWidgets('PaddleRangeSliderValueIndicatorShape skips all painting at zero scale', (WidgetTester tester) async { testWidgets('PaddleRangeSliderValueIndicatorShape skips all painting at zero scale', (WidgetTester tester) async {
// Pump a slider with just a value indicator. debugDisableShadows = false;
await tester.pumpWidget(_buildRangeApp( try {
ThemeData().sliderTheme.copyWith( // Pump a slider with just a value indicator.
trackHeight: 0, await tester.pumpWidget(_buildRangeApp(
rangeValueIndicatorShape: const PaddleRangeSliderValueIndicatorShape(), ThemeData().sliderTheme.copyWith(
), trackHeight: 0,
values: const RangeValues(0, 0.5), rangeValueIndicatorShape: const PaddleRangeSliderValueIndicatorShape(),
divisions: 4, ),
)); values: const RangeValues(0, 0.5),
divisions: 4,
));
// final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider)); // final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay)); final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
// Tap the center of the track to kick off the animation of the value indicator. // Tap the center of the track to kick off the animation of the value indicator.
final Offset center = tester.getCenter(find.byType(RangeSlider)); final Offset center = tester.getCenter(find.byType(RangeSlider));
final TestGesture gesture = await tester.startGesture(center); final TestGesture gesture = await tester.startGesture(center);
// No value indicator path to paint at scale 0. // No value indicator path to paint at scale 0.
await tester.pump(); await tester.pump();
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 0)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 0));
// Painting a path for each value indicator. // Painting a path for each value indicator.
await tester.pump(const Duration(milliseconds: 16)); await tester.pump(const Duration(milliseconds: 16));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
await gesture.up(); await gesture.up();
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('Default range indicator shape skips all painting at zero scale', (WidgetTester tester) async { testWidgets('Default range indicator shape skips all painting at zero scale', (WidgetTester tester) async {
// Pump a slider with just a value indicator. debugDisableShadows = false;
await tester.pumpWidget(_buildRangeApp( try {
ThemeData().sliderTheme.copyWith( // Pump a slider with just a value indicator.
trackHeight: 0, await tester.pumpWidget(_buildRangeApp(
overlayShape: SliderComponentShape.noOverlay, ThemeData().sliderTheme.copyWith(
thumbShape: SliderComponentShape.noThumb, trackHeight: 0,
tickMarkShape: SliderTickMarkShape.noTickMark, overlayShape: SliderComponentShape.noOverlay,
showValueIndicator: ShowValueIndicator.always, thumbShape: SliderComponentShape.noThumb,
), tickMarkShape: SliderTickMarkShape.noTickMark,
values: const RangeValues(0, 0.5), showValueIndicator: ShowValueIndicator.always,
divisions: 4, ),
)); values: const RangeValues(0, 0.5),
divisions: 4,
));
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay)); final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
// Tap the center of the track to kick off the animation of the value indicator. // Tap the center of the track to kick off the animation of the value indicator.
final Offset center = tester.getCenter(find.byType(RangeSlider)); final Offset center = tester.getCenter(find.byType(RangeSlider));
final TestGesture gesture = await tester.startGesture(center); final TestGesture gesture = await tester.startGesture(center);
// No value indicator path to paint at scale 0. // No value indicator path to paint at scale 0.
await tester.pump(); await tester.pump();
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 0)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 0));
// Painting a path for each value indicator. // Painting a path for each value indicator.
await tester.pump(const Duration(milliseconds: 16)); await tester.pump(const Duration(milliseconds: 16));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
await gesture.up(); await gesture.up();
} finally {
debugDisableShadows = true;
}
}); });
testWidgets('activeTrackRadius is taken into account when painting the border of the active track', (WidgetTester tester) async { testWidgets('activeTrackRadius is taken into account when painting the border of the active track', (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