Unverified Commit 281f1421 authored by Viren Khatri's avatar Viren Khatri Committed by GitHub

adds `trackRadius` to `ScrollbarPainter` and `RawScrollbar` (#98018)

parent 9369bd32
......@@ -86,6 +86,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
double mainAxisMargin = 0.0,
double crossAxisMargin = 0.0,
Radius? radius,
Radius? trackRadius,
OutlinedBorder? shape,
double minLength = _kMinThumbExtent,
double? minOverscrollLength,
......@@ -117,6 +118,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
_minLength = minLength,
_trackColor = trackColor,
_trackBorderColor = trackBorderColor,
_trackRadius = trackRadius,
_scrollbarOrientation = scrollbarOrientation,
_minOverscrollLength = minOverscrollLength ?? minLength,
_ignorePointer = ignorePointer {
......@@ -159,6 +161,19 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners();
}
/// [Radius] of corners of the Scrollbar's track.
///
/// Scrollbar's track will be rectangular if [trackRadius] is null.
Radius? get trackRadius => _trackRadius;
Radius? _trackRadius;
set trackRadius(Radius? value) {
if (trackRadius == value)
return;
_trackRadius = value;
notifyListeners();
}
/// [TextDirection] of the [BuildContext] which dictates the side of the
/// screen the scrollbar appears in (the trailing side). Must be set prior to
/// calling paint.
......@@ -496,7 +511,11 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
// Paint if the opacity dictates visibility
if (fadeoutOpacityAnimation.value != 0.0) {
// Track
canvas.drawRect(_trackRect!, _paintTrack());
if (trackRadius == null) {
canvas.drawRect(_trackRect!, _paintTrack());
} else {
canvas.drawRRect(RRect.fromRectAndRadius(_trackRect!, trackRadius!), _paintTrack());
}
// Track Border
canvas.drawLine(borderStart, borderEnd, _paintTrack(isBorder: true));
if (radius != null) {
......@@ -741,6 +760,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|| mainAxisMargin != oldDelegate.mainAxisMargin
|| crossAxisMargin != oldDelegate.crossAxisMargin
|| radius != oldDelegate.radius
|| trackRadius != oldDelegate.trackRadius
|| shape != oldDelegate.shape
|| padding != oldDelegate.padding
|| minLength != oldDelegate.minLength
......@@ -880,6 +900,7 @@ class RawScrollbar extends StatefulWidget {
this.minThumbLength = _kMinThumbExtent,
this.minOverscrollLength,
this.trackVisibility,
this.trackRadius,
this.trackColor,
this.trackBorderColor,
this.fadeDuration = _kScrollbarFadeDuration,
......@@ -1224,6 +1245,12 @@ class RawScrollbar extends StatefulWidget {
/// [MaterialState]s by using [ScrollbarThemeData.trackVisibility].
final bool? trackVisibility;
/// The [Radius] of the scrollbar track's rounded rectangle corners.
///
/// Scrollbar's track will be rectangular if [trackRadius] is null, which is
/// the default behavior.
final Radius? trackRadius;
/// The color of the scrollbar track.
///
/// The scrollbar track will only be visible when [trackVisibility] and
......@@ -1380,6 +1407,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
fadeoutOpacityAnimation: _fadeoutOpacityAnimation,
thickness: widget.thickness ?? _kScrollbarThickness,
radius: widget.radius,
trackRadius: widget.trackRadius,
scrollbarOrientation: widget.scrollbarOrientation,
mainAxisMargin: widget.mainAxisMargin,
shape: widget.shape,
......@@ -1513,6 +1541,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
void updateScrollbarPainter() {
scrollbarPainter
..color = widget.thumbColor ?? const Color(0x66BCBCBC)
..trackRadius = widget.trackRadius
..trackColor = _showTrack ? const Color(0x08000000) : const Color(0x00000000)
..trackBorderColor = _showTrack ? const Color(0x1a000000) : const Color(0x00000000)
..textDirection = Directionality.of(context)
......
......@@ -25,6 +25,7 @@ ScrollbarPainter _buildPainter({
double mainAxisMargin = 0.0,
double crossAxisMargin = 0.0,
Radius? radius,
Radius? trackRadius,
double minLength = _kMinThumbExtent,
double? minOverscrollLength,
ScrollbarOrientation? scrollbarOrientation,
......@@ -38,6 +39,7 @@ ScrollbarPainter _buildPainter({
mainAxisMargin: mainAxisMargin,
crossAxisMargin: crossAxisMargin,
radius: radius,
trackRadius: trackRadius,
minLength: minLength,
minOverscrollLength: minOverscrollLength ?? minLength,
fadeoutOpacityAnimation: kAlwaysCompleteAnimation,
......@@ -47,12 +49,18 @@ ScrollbarPainter _buildPainter({
class _DrawRectOnceCanvas extends Fake implements Canvas {
List<Rect> rects = <Rect>[];
List<RRect> rrects = <RRect>[];
@override
void drawRect(Rect rect, Paint paint) {
rects.add(rect);
}
@override
void drawRRect(ui.RRect rrect, ui.Paint paint) {
rrects.add(rrect);
}
@override
void drawLine(Offset p1, Offset p2, Paint paint) {}
}
......@@ -62,9 +70,11 @@ void main() {
ScrollbarPainter painter;
Rect captureRect() => testCanvas.rects.removeLast();
RRect captureRRect() => testCanvas.rrects.removeLast();
tearDown(() {
testCanvas.rects.clear();
testCanvas.rrects.clear();
});
final ScrollMetrics defaultMetrics = FixedScrollMetrics(
......@@ -629,6 +639,37 @@ void main() {
},
);
test('trackRadius and radius is respected', () {
const double minLen = 3.5;
const Size size = Size(600, 10);
final ScrollMetrics metrics = defaultMetrics.copyWith(
maxScrollExtent: 100000,
viewportDimension: size.height,
);
painter = _buildPainter(
trackRadius: const Radius.circular(2.0),
radius: const Radius.circular(3.0),
minLength: minLen,
minOverscrollLength: minLen,
scrollMetrics: metrics,
);
painter.paint(testCanvas, size);
final RRect thumbRRect = captureRRect(); // thumb
expect(thumbRRect.blRadius, const Radius.circular(3.0));
expect(thumbRRect.brRadius, const Radius.circular(3.0));
expect(thumbRRect.tlRadius, const Radius.circular(3.0));
expect(thumbRRect.trRadius, const Radius.circular(3.0));
final RRect trackRRect = captureRRect(); // track
expect(trackRRect.blRadius, const Radius.circular(2.0));
expect(trackRRect.brRadius, const Radius.circular(2.0));
expect(trackRRect.tlRadius, const Radius.circular(2.0));
expect(trackRRect.trRadius, const Radius.circular(2.0));
});
testWidgets('ScrollbarPainter asserts if no TextDirection has been provided', (WidgetTester tester) async {
final ScrollbarPainter painter = ScrollbarPainter(
color: _kScrollbarColor,
......@@ -691,7 +732,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 240.0, 800.0, 600.0),
color: const Color(0x66BCBCBC),
),
),
);
// Tap on the track area above the thumb.
......@@ -706,7 +747,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 360.0),
color: const Color(0x66BCBCBC),
),
),
);
});
......@@ -736,7 +777,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0),
color: const Color(0x66BCBCBC),
),
),
);
await tester.pump(const Duration(seconds: 3));
......@@ -749,7 +790,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0),
color: const Color(0x66BCBCBC),
),
),
);
await gesture.up();
......@@ -764,7 +805,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0),
color: const Color(0x4fbcbcbc),
),
),
);
});
......@@ -794,7 +835,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0),
color: const Color(0x66BCBCBC),
),
),
);
final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
......@@ -811,7 +852,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0),
color: const Color(0x66BCBCBC),
),
),
);
});
......@@ -940,7 +981,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 90.0),
color: const Color(0x66BCBCBC),
),
),
);
// Drag the thumb down to scroll down.
......@@ -962,7 +1003,7 @@ void main() {
..rect(
rect: const Rect.fromLTRB(794.0, 10.0, 800.0, 100.0),
color: const Color(0x66BCBCBC),
),
),
);
});
......@@ -2206,6 +2247,7 @@ void main() {
double mainAxisMargin = 0.0,
double crossAxisMargin = 0.0,
Radius? radius,
Radius? trackRadius,
OutlinedBorder? shape,
double minLength = _kMinThumbExtent,
double? minOverscrollLength,
......@@ -2222,6 +2264,7 @@ void main() {
mainAxisMargin: mainAxisMargin,
crossAxisMargin: crossAxisMargin,
radius: radius,
trackRadius: trackRadius,
shape: shape,
minLength: minLength,
minOverscrollLength: minOverscrollLength,
......@@ -2240,6 +2283,7 @@ void main() {
expect(painter.shouldRepaint(createPainter(mainAxisMargin: 1.0)), true);
expect(painter.shouldRepaint(createPainter(crossAxisMargin: 1.0)), true);
expect(painter.shouldRepaint(createPainter(radius: const Radius.circular(1.0))), true);
expect(painter.shouldRepaint(createPainter(trackRadius: const Radius.circular(1.0))), true);
expect(painter.shouldRepaint(createPainter(shape: const CircleBorder(side: BorderSide(width: 2.0)))), true);
expect(painter.shouldRepaint(createPainter(minLength: _kMinThumbExtent + 1.0)), true);
expect(painter.shouldRepaint(createPainter(minOverscrollLength: 1.0)), true);
......@@ -2289,6 +2333,45 @@ void main() {
);
});
testWidgets('trackRadius and radius properties of RawScrollbar can draw RoundedRectangularRect', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: PrimaryScrollController(
controller: scrollController,
child: RawScrollbar(
thumbVisibility: true,
trackVisibility: true,
trackRadius: const Radius.circular(1.0),
radius: const Radius.circular(2.0),
controller: scrollController,
child: const SingleChildScrollView(
child: SizedBox(width: 4000.0, height: 4000.0),
),
),
),
),
),
);
await tester.pumpAndSettle();
expect(scrollController.offset, 0.0);
expect(
find.byType(RawScrollbar),
paints
..rrect(
rrect: RRect.fromLTRBR(794.0, 0.0, 800.0, 600.0, const Radius.circular(1.0)),
color: const Color(0x08000000),
)
..rrect(
rrect: RRect.fromLTRBR(794.0, 0.0, 800.0, 90.0, const Radius.circular(2.0)),
color: const Color(0x66bcbcbc),
)
);
});
testWidgets('Scrollbar asserts that a visible track has a visible thumb', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
Widget _buildApp() {
......
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