parent
a1a360bf13
commit
8ffe7c56d7
1
AUTHORS
1
AUTHORS
@ -80,3 +80,4 @@ Ludwik Trammer <ludwik@gmail.com>
|
|||||||
Marian Triebe <m.triebe@live.de>
|
Marian Triebe <m.triebe@live.de>
|
||||||
Alexis Rouillard <contact@arouillard.fr>
|
Alexis Rouillard <contact@arouillard.fr>
|
||||||
Mirko Mucaria <skogsfrae@gmail.com>
|
Mirko Mucaria <skogsfrae@gmail.com>
|
||||||
|
Karol Czeryna <karol.czeryna@gmail.com>
|
||||||
|
@ -912,26 +912,69 @@ class _SwitchPainter extends ToggleablePainter {
|
|||||||
? (currentValue < 0.5 ? onInactiveThumbImageError : onActiveThumbImageError)
|
? (currentValue < 0.5 ? onInactiveThumbImageError : onActiveThumbImageError)
|
||||||
: onInactiveThumbImageError;
|
: onInactiveThumbImageError;
|
||||||
|
|
||||||
// Paint the track
|
|
||||||
final Paint paint = Paint()
|
final Paint paint = Paint()
|
||||||
..color = trackColor;
|
..color = trackColor;
|
||||||
const double trackHorizontalPadding = kRadialReactionRadius - _kTrackRadius;
|
|
||||||
|
final Offset trackPaintOffset = _computeTrackPaintOffset(size, _kTrackWidth, _kTrackHeight);
|
||||||
|
final Offset thumbPaintOffset = _computeThumbPaintOffset(trackPaintOffset, visualPosition);
|
||||||
|
final Offset radialReactionOrigin = Offset(thumbPaintOffset.dx + _kThumbRadius, size.height / 2);
|
||||||
|
|
||||||
|
_paintTrackWith(canvas, paint, trackPaintOffset);
|
||||||
|
paintRadialReaction(canvas: canvas, origin: radialReactionOrigin);
|
||||||
|
_paintThumbWith(
|
||||||
|
thumbPaintOffset,
|
||||||
|
canvas,
|
||||||
|
currentValue,
|
||||||
|
thumbColor,
|
||||||
|
thumbImage,
|
||||||
|
thumbErrorListener,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes canvas offset for track's upper left corner
|
||||||
|
Offset _computeTrackPaintOffset(Size canvasSize, double trackWidth, double trackHeight) {
|
||||||
|
final double horizontalOffset = (canvasSize.width - _kTrackWidth) / 2.0;
|
||||||
|
final double verticalOffset = (canvasSize.height - _kTrackHeight) / 2.0;
|
||||||
|
|
||||||
|
return Offset(horizontalOffset, verticalOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes canvas offset for thumb's upper left corner as if it were a
|
||||||
|
/// square
|
||||||
|
Offset _computeThumbPaintOffset(Offset trackPaintOffset, double visualPosition) {
|
||||||
|
// How much thumb radius extends beyond the track
|
||||||
|
const double additionalThumbRadius = _kThumbRadius - _kTrackRadius;
|
||||||
|
|
||||||
|
final double horizontalProgress = visualPosition * trackInnerLength;
|
||||||
|
final double thumbHorizontalOffset = trackPaintOffset.dx - additionalThumbRadius + horizontalProgress;
|
||||||
|
final double thumbVerticalOffset = trackPaintOffset.dy - additionalThumbRadius;
|
||||||
|
|
||||||
|
return Offset(thumbHorizontalOffset, thumbVerticalOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _paintTrackWith(Canvas canvas, Paint paint, Offset trackPaintOffset) {
|
||||||
final Rect trackRect = Rect.fromLTWH(
|
final Rect trackRect = Rect.fromLTWH(
|
||||||
trackHorizontalPadding,
|
trackPaintOffset.dx,
|
||||||
(size.height - _kTrackHeight) / 2.0,
|
trackPaintOffset.dy,
|
||||||
size.width - 2.0 * trackHorizontalPadding,
|
_kTrackWidth,
|
||||||
_kTrackHeight,
|
_kTrackHeight,
|
||||||
);
|
);
|
||||||
final RRect trackRRect = RRect.fromRectAndRadius(trackRect, const Radius.circular(_kTrackRadius));
|
final RRect trackRRect = RRect.fromRectAndRadius(
|
||||||
canvas.drawRRect(trackRRect, paint);
|
trackRect,
|
||||||
|
const Radius.circular(_kTrackRadius),
|
||||||
final Offset thumbPosition = Offset(
|
|
||||||
kRadialReactionRadius + visualPosition * trackInnerLength,
|
|
||||||
size.height / 2.0,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
paintRadialReaction(canvas: canvas, origin: thumbPosition);
|
canvas.drawRRect(trackRRect, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _paintThumbWith(
|
||||||
|
Offset thumbPaintOffset,
|
||||||
|
Canvas canvas,
|
||||||
|
double currentValue,
|
||||||
|
Color thumbColor,
|
||||||
|
ImageProvider? thumbImage,
|
||||||
|
ImageErrorListener? thumbErrorListener,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
_isPainting = true;
|
_isPainting = true;
|
||||||
if (_cachedThumbPainter == null || thumbColor != _cachedThumbColor || thumbImage != _cachedThumbImage || thumbErrorListener != _cachedThumbErrorListener) {
|
if (_cachedThumbPainter == null || thumbColor != _cachedThumbColor || thumbImage != _cachedThumbImage || thumbErrorListener != _cachedThumbErrorListener) {
|
||||||
@ -946,9 +989,10 @@ class _SwitchPainter extends ToggleablePainter {
|
|||||||
// The thumb contracts slightly during the animation
|
// The thumb contracts slightly during the animation
|
||||||
final double inset = 1.0 - (currentValue - 0.5).abs() * 2.0;
|
final double inset = 1.0 - (currentValue - 0.5).abs() * 2.0;
|
||||||
final double radius = _kThumbRadius - inset;
|
final double radius = _kThumbRadius - inset;
|
||||||
|
|
||||||
thumbPainter.paint(
|
thumbPainter.paint(
|
||||||
canvas,
|
canvas,
|
||||||
thumbPosition - Offset(radius, radius),
|
thumbPaintOffset + Offset(0, inset),
|
||||||
configuration.copyWith(size: Size.fromRadius(radius)),
|
configuration.copyWith(size: Size.fromRadius(radius)),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -92,6 +92,57 @@ void main() {
|
|||||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Switch does not get distorted upon changing constraints with parent', (WidgetTester tester) async {
|
||||||
|
const double maxWidth = 300;
|
||||||
|
const double maxHeight = 100;
|
||||||
|
|
||||||
|
const ValueKey<String> boundaryKey = ValueKey<String>('switch container');
|
||||||
|
|
||||||
|
Widget buildSwitch({required double width, required double height}) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: SizedBox(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
child: RepaintBoundary(
|
||||||
|
key: boundaryKey,
|
||||||
|
child: SizedBox(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
child: Switch(
|
||||||
|
dragStartBehavior: DragStartBehavior.down,
|
||||||
|
value: true,
|
||||||
|
onChanged: (_) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildSwitch(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
));
|
||||||
|
await expectLater(
|
||||||
|
find.byKey(boundaryKey),
|
||||||
|
matchesGoldenFile('switch_test.big.on.png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildSwitch(
|
||||||
|
width: 20,
|
||||||
|
height: 10,
|
||||||
|
));
|
||||||
|
await expectLater(
|
||||||
|
find.byKey(boundaryKey),
|
||||||
|
matchesGoldenFile('switch_test.small.on.png'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Switch can drag (LTR)', (WidgetTester tester) async {
|
testWidgets('Switch can drag (LTR)', (WidgetTester tester) async {
|
||||||
bool value = false;
|
bool value = false;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user