diff --git a/bin/internal/goldens.version b/bin/internal/goldens.version index 9c4233a3fc3..c6c5ed784e1 100644 --- a/bin/internal/goldens.version +++ b/bin/internal/goldens.version @@ -1 +1 @@ -ae7615ce466a548b41a0f7b9860ec453646f73e9 +0728c1b6e968602e173d0153a88d9cfb932d8c9b diff --git a/packages/flutter/lib/src/cupertino/colors.dart b/packages/flutter/lib/src/cupertino/colors.dart index 413a82638c0..80dc57be050 100644 --- a/packages/flutter/lib/src/cupertino/colors.dart +++ b/packages/flutter/lib/src/cupertino/colors.dart @@ -1014,14 +1014,14 @@ const CupertinoSystemColorsData _kSystemColorsFallback = CupertinoSystemColorsDa darkHighContrastElevatedColor: Color.fromARGB(112, 120, 120, 128), ), secondarySystemFill: CupertinoDynamicColor( - color: Color.fromARGB(153, 60, 60, 67), - darkColor: Color.fromARGB(153, 235, 235, 245), - highContrastColor: Color.fromARGB(173, 60, 60, 67), - darkHighContrastColor: Color.fromARGB(173, 235, 235, 245), - elevatedColor: Color.fromARGB(153, 60, 60, 67), - darkElevatedColor: Color.fromARGB(153, 235, 235, 245), - highContrastElevatedColor: Color.fromARGB(173, 60, 60, 67), - darkHighContrastElevatedColor: Color.fromARGB(173, 235, 235, 245), + color: Color.fromARGB(40, 120, 120, 128), + darkColor: Color.fromARGB(81, 120, 120, 128), + highContrastColor: Color.fromARGB(61, 120, 120, 128), + darkHighContrastColor: Color.fromARGB(102, 120, 120, 128), + elevatedColor: Color.fromARGB(40, 120, 120, 128), + darkElevatedColor: Color.fromARGB(81, 120, 120, 128), + highContrastElevatedColor: Color.fromARGB(61, 120, 120, 128), + darkHighContrastElevatedColor: Color.fromARGB(102, 120, 120, 128), ), tertiarySystemFill: CupertinoDynamicColor( color: Color.fromARGB(30, 118, 118, 128), diff --git a/packages/flutter/lib/src/cupertino/scrollbar.dart b/packages/flutter/lib/src/cupertino/scrollbar.dart index f80356cf8ec..54f8eada043 100644 --- a/packages/flutter/lib/src/cupertino/scrollbar.dart +++ b/packages/flutter/lib/src/cupertino/scrollbar.dart @@ -8,19 +8,25 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'colors.dart'; + // All values eyeballed. -const Color _kScrollbarColor = Color(0x99777777); const double _kScrollbarMinLength = 36.0; const double _kScrollbarMinOverscrollLength = 8.0; -const Radius _kScrollbarRadius = Radius.circular(1.5); -const Radius _kScrollbarRadiusDragging = Radius.circular(4.0); const Duration _kScrollbarTimeToFade = Duration(milliseconds: 1200); const Duration _kScrollbarFadeDuration = Duration(milliseconds: 250); const Duration _kScrollbarResizeDuration = Duration(milliseconds: 150); -// These values are measured using screenshots from an iPhone XR 13.0 simulator. -const double _kScrollbarThickness = 2.5; +// Extracted from iOS 13.1 beta using Debug View Hierarchy. +const Color _kScrollbarColor = CupertinoDynamicColor.withBrightness( + color: Color(0x59000000), + darkColor: Color(0x80FFFFFF), +); +const double _kScrollbarThickness = 3; const double _kScrollbarThicknessDragging = 8.0; +const Radius _kScrollbarRadius = Radius.circular(1.5); +const Radius _kScrollbarRadiusDragging = Radius.circular(4.0); + // This is the amount of space from the top of a vertical scrollbar to the // top edge of the scrollable, measured when the vertical scrollbar overscrolls // to the top. @@ -101,7 +107,6 @@ class CupertinoScrollbar extends StatefulWidget { class _CupertinoScrollbarState extends State with TickerProviderStateMixin { final GlobalKey _customPaintKey = GlobalKey(); ScrollbarPainter _painter; - TextDirection _textDirection; AnimationController _fadeoutAnimationController; Animation _fadeoutOpacityAnimation; @@ -141,15 +146,22 @@ class _CupertinoScrollbarState extends State with TickerProv @override void didChangeDependencies() { super.didChangeDependencies(); - _textDirection = Directionality.of(context); - _painter = _buildCupertinoScrollbarPainter(); + if (_painter == null) { + _painter = _buildCupertinoScrollbarPainter(context); + } + else { + _painter + ..textDirection = Directionality.of(context) + ..color = CupertinoDynamicColor.resolve(_kScrollbarColor, context) + ..padding = MediaQuery.of(context).padding; + } } /// Returns a [ScrollbarPainter] visually styled like the iOS scrollbar. - ScrollbarPainter _buildCupertinoScrollbarPainter() { + ScrollbarPainter _buildCupertinoScrollbarPainter(BuildContext context) { return ScrollbarPainter( - color: _kScrollbarColor, - textDirection: _textDirection, + color: CupertinoDynamicColor.resolve(_kScrollbarColor, context), + textDirection: Directionality.of(context), thickness: _thickness, fadeoutOpacityAnimation: _fadeoutOpacityAnimation, mainAxisMargin: _kScrollbarMainAxisMargin, @@ -353,9 +365,7 @@ class _CupertinoScrollbarState extends State with TickerProv child: CustomPaint( key: _customPaintKey, foregroundPainter: _painter, - child: RepaintBoundary( - child: widget.child, - ), + child: RepaintBoundary(child: widget.child), ), ), ), diff --git a/packages/flutter/lib/src/cupertino/slider.dart b/packages/flutter/lib/src/cupertino/slider.dart index 7ea9f5025e4..33da482c485 100644 --- a/packages/flutter/lib/src/cupertino/slider.dart +++ b/packages/flutter/lib/src/cupertino/slider.dart @@ -474,8 +474,6 @@ class _RenderCupertinoSlider extends RenderConstrainedBox { _drag.addPointer(event); } - final CupertinoThumbPainter _thumbPainter = CupertinoThumbPainter(); - @override void paint(PaintingContext context, Offset offset) { double visualPosition; @@ -514,7 +512,7 @@ class _RenderCupertinoSlider extends RenderConstrainedBox { } final Offset thumbCenter = Offset(trackActive, trackCenter); - _thumbPainter.paint(canvas, Rect.fromCircle(center: thumbCenter, radius: CupertinoThumbPainter.radius)); + const CupertinoThumbPainter().paint(canvas, Rect.fromCircle(center: thumbCenter, radius: CupertinoThumbPainter.radius)); } @override diff --git a/packages/flutter/lib/src/cupertino/switch.dart b/packages/flutter/lib/src/cupertino/switch.dart index de6ef647f2b..57056f6b977 100644 --- a/packages/flutter/lib/src/cupertino/switch.dart +++ b/packages/flutter/lib/src/cupertino/switch.dart @@ -96,8 +96,8 @@ class CupertinoSwitch extends StatefulWidget { /// The color to use when this switch is on. /// - /// Defaults to [CupertinoColors.activeGreen] when null and ignores the - /// [CupertinoTheme] in accordance to native iOS behavior. + /// Defaults to [CupertinoSystemColorsData.systemGreen] when null and ignores + /// the [CupertinoTheme] in accordance to native iOS behavior. final Color activeColor; /// {@template flutter.cupertino.switch.dragStartBehavior} @@ -140,7 +140,10 @@ class _CupertinoSwitchState extends State with TickerProviderSt opacity: widget.onChanged == null ? _kCupertinoSwitchDisabledOpacity : 1.0, child: _CupertinoSwitchRenderObjectWidget( value: widget.value, - activeColor: widget.activeColor ?? CupertinoColors.activeGreen, + activeColor: CupertinoDynamicColor.resolve( + widget.activeColor ?? CupertinoSystemColors.of(context).systemGreen, + context, + ), onChanged: widget.onChanged, vsync: this, dragStartBehavior: widget.dragStartBehavior, @@ -170,6 +173,7 @@ class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget { return _RenderCupertinoSwitch( value: value, activeColor: activeColor, + trackColor: CupertinoDynamicColor.resolve(CupertinoSystemColors.of(context).secondarySystemFill, context), onChanged: onChanged, textDirection: Directionality.of(context), vsync: vsync, @@ -182,6 +186,7 @@ class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget { renderObject ..value = value ..activeColor = activeColor + ..trackColor = CupertinoDynamicColor.resolve(CupertinoSystemColors.of(context).secondarySystemFill, context) ..onChanged = onChanged ..textDirection = Directionality.of(context) ..vsync = vsync @@ -200,7 +205,6 @@ const double _kSwitchHeight = 39.0; // Opacity of a disabled switch, as eye-balled from iOS Simulator on Mac. const double _kCupertinoSwitchDisabledOpacity = 0.5; -const Color _kTrackColor = CupertinoColors.lightBackgroundGray; const Duration _kReactionDuration = Duration(milliseconds: 300); const Duration _kToggleDuration = Duration(milliseconds: 200); @@ -208,6 +212,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { _RenderCupertinoSwitch({ @required bool value, @required Color activeColor, + @required Color trackColor, ValueChanged onChanged, @required TextDirection textDirection, @required TickerProvider vsync, @@ -217,6 +222,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { assert(vsync != null), _value = value, _activeColor = activeColor, + _trackColor = trackColor, _onChanged = onChanged, _textDirection = textDirection, _vsync = vsync, @@ -295,6 +301,16 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { markNeedsPaint(); } + Color get trackColor => _trackColor; + Color _trackColor; + set trackColor(Color value) { + assert(value != null); + if (value == _trackColor) + return; + _trackColor = value; + markNeedsPaint(); + } + ValueChanged get onChanged => _onChanged; ValueChanged _onChanged; set onChanged(ValueChanged value) { @@ -458,8 +474,6 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { config.isToggled = _value; } - final CupertinoThumbPainter _thumbPainter = CupertinoThumbPainter(); - @override void paint(PaintingContext context, Offset offset) { final Canvas canvas = context.canvas; @@ -478,7 +492,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { } final Paint paint = Paint() - ..color = Color.lerp(_kTrackColor, activeColor, currentValue); + ..color = Color.lerp(trackColor, activeColor, currentValue); final Rect trackRect = Rect.fromLTWH( offset.dx + (size.width - _kTrackWidth) / 2.0, @@ -509,7 +523,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { ); context.pushClipRRect(needsCompositing, Offset.zero, thumbBounds, trackRRect, (PaintingContext innerContext, Offset offset) { - _thumbPainter.paint(innerContext.canvas, thumbBounds); + const CupertinoThumbPainter.switchThumb().paint(innerContext.canvas, thumbBounds); }); } diff --git a/packages/flutter/lib/src/cupertino/thumb_painter.dart b/packages/flutter/lib/src/cupertino/thumb_painter.dart index 030c8ab495d..985e0e5502a 100644 --- a/packages/flutter/lib/src/cupertino/thumb_painter.dart +++ b/packages/flutter/lib/src/cupertino/thumb_painter.dart @@ -6,27 +6,62 @@ import 'package:flutter/painting.dart'; import 'colors.dart'; -/// Paints an iOS-style slider thumb. +const Color _kThumbBorderColor = Color(0x0A000000); + +const List _kSwitchBoxShadows = [ + BoxShadow( + color: Color(0x26000000), + offset: Offset(0, 3), + blurRadius: 8.0, + ), + BoxShadow( + color: Color(0x0F000000), + offset: Offset(0, 3), + blurRadius: 1.0, + ), +]; + +const List _kSliderBoxShadows = [ + BoxShadow( + color: Color(0x26000000), + offset: Offset(0, 3), + blurRadius: 8.0, + ), + BoxShadow( + color: Color(0x29000000), + offset: Offset(0, 1), + blurRadius: 1.0, + ), + BoxShadow( + color: Color(0x1A000000), + offset: Offset(0, 3), + blurRadius: 1.0, + ), +]; + +/// Paints an iOS-style slider thumb or switch thumb. /// /// Used by [CupertinoSwitch] and [CupertinoSlider]. class CupertinoThumbPainter { /// Creates an object that paints an iOS-style slider thumb. - CupertinoThumbPainter({ + const CupertinoThumbPainter({ this.color = CupertinoColors.white, - this.shadowColor = const Color(0x2C000000), - }) : _shadowPaint = BoxShadow( - color: shadowColor, - blurRadius: 1.0, - ).toPaint(); + this.shadows = _kSliderBoxShadows, + }) : assert(shadows != null); + + /// Creates an object that paints an iOS-style switch thumb. + const CupertinoThumbPainter.switchThumb({ + Color color = CupertinoColors.white, + List shadows = _kSwitchBoxShadows, + }) : this(color: color, shadows: shadows); /// The color of the interior of the thumb. final Color color; - /// The color of the shadow case by the thumb. - final Color shadowColor; - - /// The paint used to draw the shadow case by the thumb. - final Paint _shadowPaint; + /// The list of [BoxShadow] to paint below the thumb. + /// + /// Must not be null. + final List shadows; /// Half the default diameter of the thumb. static const double radius = 14.0; @@ -44,8 +79,13 @@ class CupertinoThumbPainter { Radius.circular(rect.shortestSide / 2.0), ); - canvas.drawRRect(rrect, _shadowPaint); - canvas.drawRRect(rrect.shift(const Offset(0.0, 3.0)), _shadowPaint); + for (BoxShadow shadow in shadows) + canvas.drawRRect(rrect.shift(shadow.offset), shadow.toPaint()); + + canvas.drawRRect( + rrect.inflate(0.5), + Paint()..color = _kThumbBorderColor, + ); canvas.drawRRect(rrect, Paint()..color = color); } } diff --git a/packages/flutter/lib/src/widgets/scrollbar.dart b/packages/flutter/lib/src/widgets/scrollbar.dart index e2951222308..442178efc73 100644 --- a/packages/flutter/lib/src/widgets/scrollbar.dart +++ b/packages/flutter/lib/src/widgets/scrollbar.dart @@ -44,11 +44,11 @@ const double _kMinInteractiveSize = 48.0; class ScrollbarPainter extends ChangeNotifier implements CustomPainter { /// Creates a scrollbar with customizations given by construction arguments. ScrollbarPainter({ - @required this.color, - @required this.textDirection, + @required Color color, + @required TextDirection textDirection, @required this.thickness, @required this.fadeoutOpacityAnimation, - this.padding = EdgeInsets.zero, + EdgeInsets padding = EdgeInsets.zero, this.mainAxisMargin = 0.0, this.crossAxisMargin = 0.0, this.radius, @@ -66,16 +66,37 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { assert(minOverscrollLength == null || minOverscrollLength >= 0), assert(padding != null), assert(padding.isNonNegative), + _color = color, + _textDirection = textDirection, + _padding = padding, minOverscrollLength = minOverscrollLength ?? minLength { fadeoutOpacityAnimation.addListener(notifyListeners); } /// [Color] of the thumb. Mustn't be null. - final Color color; + Color get color => _color; + Color _color; + set color(Color value) { + assert(value != null); + if (color == value) + return; + + _color = value; + notifyListeners(); + } /// [TextDirection] of the [BuildContext] which dictates the side of the /// screen the scrollbar appears in (the trailing side). Mustn't be null. - final TextDirection textDirection; + TextDirection get textDirection => _textDirection; + TextDirection _textDirection; + set textDirection(TextDirection value) { + assert(value != null); + if (textDirection == value) + return; + + _textDirection = value; + notifyListeners(); + } /// Thickness of the scrollbar in its cross-axis in logical pixels. Mustn't be null. double thickness; @@ -110,7 +131,17 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { /// /// Defaults to [EdgeInsets.zero]. Must not be null and offsets from all four /// directions must be greater than or equal to zero. - final EdgeInsets padding; + EdgeInsets get padding => _padding; + EdgeInsets _padding; + set padding(EdgeInsets value) { + assert(value != null); + if (padding == value) + return; + + _padding = value; + notifyListeners(); + } + /// The preferred smallest size the scrollbar can shrink to when the total /// scrollable extent is large, the current visible viewport is small, and the @@ -162,8 +193,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { } Paint get _paint { - return Paint()..color = - color.withOpacity(color.opacity * fadeoutOpacityAnimation.value); + return Paint() + ..color = color.withOpacity(color.opacity * fadeoutOpacityAnimation.value); } void _paintThumbCrossAxis(Canvas canvas, Size size, double thumbOffset, double thumbExtent, AxisDirection direction) { diff --git a/packages/flutter/test/cupertino/scrollbar_paint_test.dart b/packages/flutter/test/cupertino/scrollbar_paint_test.dart index 3959b0ce53d..5f3f58581e1 100644 --- a/packages/flutter/test/cupertino/scrollbar_paint_test.dart +++ b/packages/flutter/test/cupertino/scrollbar_paint_test.dart @@ -7,7 +7,7 @@ import 'package:flutter_test/flutter_test.dart'; import '../rendering/mock_canvas.dart'; -const Color _kScrollbarColor = Color(0x99777777); +const Color _kScrollbarColor = Color(0x59000000); // The `y` offset has to be larger than `ScrollDragController._bigThresholdBreakDistance` // to prevent [motionStartDistanceThreshold] from affecting the actual drag distance. @@ -42,9 +42,9 @@ void main() { color: _kScrollbarColor, rrect: RRect.fromRectAndRadius( const Rect.fromLTWH( - 800.0 - 3 - 2.5, // Screen width - margin - thickness. + 800.0 - 3 - 3, // Screen width - margin - thickness. 3.0, // Initial position is the top margin. - 2.5, // Thickness. + 3, // Thickness. // Fraction in viewport * scrollbar height - top, bottom margin. 600.0 / 4000.0 * (600.0 - 2 * 3), ), @@ -86,9 +86,9 @@ void main() { color: _kScrollbarColor, rrect: RRect.fromRectAndRadius( const Rect.fromLTWH( - 800.0 - 3 - 2.5, // Screen width - margin - thickness. + 800.0 - 3 - 3, // Screen width - margin - thickness. 44 + 20 + 3.0, // nav bar height + top margin - 2.5, // Thickness. + 3, // Thickness. // Fraction visible * (viewport size - padding - margin) // where Fraction visible = (viewport size - padding) / content size (600.0 - 34 - 44 - 20) / 4000.0 * (600.0 - 2 * 3 - 34 - 44 - 20), diff --git a/packages/flutter/test/cupertino/scrollbar_test.dart b/packages/flutter/test/cupertino/scrollbar_test.dart index ceb37c2aa32..511f94ff674 100644 --- a/packages/flutter/test/cupertino/scrollbar_test.dart +++ b/packages/flutter/test/cupertino/scrollbar_test.dart @@ -8,6 +8,11 @@ import 'package:flutter_test/flutter_test.dart'; import '../rendering/mock_canvas.dart'; +const CupertinoDynamicColor _kScrollbarColor = CupertinoDynamicColor.withBrightness( + color: Color(0x59000000), + darkColor:Color(0x80FFFFFF), +); + void main() { const Duration _kScrollbarTimeToFade = Duration(milliseconds: 1200); const Duration _kScrollbarFadeDuration = Duration(milliseconds: 250); @@ -31,14 +36,14 @@ void main() { // Scrollbar fully showing await tester.pump(const Duration(milliseconds: 500)); expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); await tester.pump(const Duration(seconds: 3)); await tester.pump(const Duration(seconds: 3)); // Still there. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); await gesture.up(); @@ -47,7 +52,44 @@ void main() { // Opacity going down now. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x77777777), + color: _kScrollbarColor.color.withAlpha(69), + )); + }); + + testWidgets('Scrollbar dark mode', (WidgetTester tester) async { + Brightness brightness = Brightness.light; + StateSetter setState; + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: StatefulBuilder( + builder: (BuildContext context, StateSetter setter) { + setState = setter; + return MediaQuery( + data: MediaQueryData(platformBrightness: brightness), + child: const CupertinoScrollbar( + child: SingleChildScrollView(child: SizedBox(width: 4000.0, height: 4000.0)), + ), + ); + }, + ), + ), + ); + + final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(SingleChildScrollView))); + await gesture.moveBy(const Offset(0.0, 10.0)); + await tester.pump(); + // Scrollbar fully showing + await tester.pumpAndSettle(); + expect(find.byType(CupertinoScrollbar), paints..rrect( + color: _kScrollbarColor.color, + )); + + setState(() { brightness = Brightness.dark; }); + await tester.pump(); + + expect(find.byType(CupertinoScrollbar), paints..rrect( + color: _kScrollbarColor.darkColor, )); }); @@ -81,7 +123,7 @@ void main() { // Scrollbar thumb is fully showing and scroll offset has moved by // scrollAmount. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); expect(scrollController.offset, scrollAmount); await scrollGesture.up(); @@ -111,7 +153,7 @@ void main() { expect(scrollController.offset, greaterThan(scrollAmount * 2)); // The scrollbar thumb is still fully visible. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); // Let the thumb fade out so all timers have resolved. @@ -149,7 +191,7 @@ void main() { // Scrollbar thumb is fully showing and scroll offset has moved by // scrollAmount. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); expect(scrollController.offset, scrollAmount); await scrollGesture.up(); @@ -182,7 +224,7 @@ void main() { expect(scrollController.offset, greaterThan(scrollAmount * 2)); // The scrollbar thumb is still fully visible. expect(find.byType(CupertinoScrollbar), paints..rrect( - color: const Color(0x99777777), + color: _kScrollbarColor.color, )); // Let the thumb fade out so all timers have resolved. diff --git a/packages/flutter/test/cupertino/switch_test.dart b/packages/flutter/test/cupertino/switch_test.dart index 5ceb15696d3..e270206a233 100644 --- a/packages/flutter/test/cupertino/switch_test.dart +++ b/packages/flutter/test/cupertino/switch_test.dart @@ -532,8 +532,8 @@ void main() { value = newValue; }); }, - ) - ) + ), + ), ); }, ), @@ -544,7 +544,7 @@ void main() { find.byKey(switchKey), matchesGoldenFile( 'switch.tap.off.png', - version: 0, + version: 1, ), ); @@ -558,7 +558,7 @@ void main() { find.byKey(switchKey), matchesGoldenFile( 'switch.tap.turningOn.png', - version: 0, + version: 1, ), ); @@ -567,9 +567,59 @@ void main() { find.byKey(switchKey), matchesGoldenFile( 'switch.tap.on.png', - version: 0, + version: 1, ), ); }); + testWidgets('Switch renders correctly in dark mode', (WidgetTester tester) async { + final Key switchKey = UniqueKey(); + bool value = false; + await tester.pumpWidget( + MediaQuery( + data: const MediaQueryData(platformBrightness: Brightness.dark), + child: Directionality( + textDirection: TextDirection.ltr, + child: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Center( + child: RepaintBoundary( + child: CupertinoSwitch( + key: switchKey, + value: value, + dragStartBehavior: DragStartBehavior.down, + onChanged: (bool newValue) { + setState(() { + value = newValue; + }); + }, + ), + ), + ); + }, + ), + ), + ), + ); + + await expectLater( + find.byKey(switchKey), + matchesGoldenFile( + 'switch.tap.off.dark.png', + version: 0, + ), + ); + + await tester.tap(find.byKey(switchKey)); + expect(value, isTrue); + + await tester.pumpAndSettle(); + await expectLater( + find.byKey(switchKey), + matchesGoldenFile( + 'switch.tap.on.dark.png', + version: 0, + ), + ); + }); }