Unverified Commit 4815b26d authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Dark mode for CupertinoSwitch and CupertinoScrollbar, Fidelity updates (#40636)

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