Unverified Commit c4cf6f18 authored by Mohammad Ghalayini's avatar Mohammad Ghalayini Committed by GitHub

Expose minThumbLength, crossAxisMargin, and minOverscrollLength on RawScrollbar (#85338)

parent 57224f81
......@@ -196,7 +196,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners();
}
/// Distance from the scrollbar's side to the nearest edge in logical pixels.
/// Distance from the scrollbar thumb to the nearest cross axis edge
/// in logical pixels.
///
/// Must not be null and defaults to 0.
double get crossAxisMargin => _crossAxisMargin;
......@@ -244,7 +245,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
}
/// The preferred smallest size the scrollbar can shrink to when the total
/// The preferred smallest size the scrollbar thumb can shrink to when the total
/// scrollable extent is large, the current visible viewport is small, and the
/// viewport is not overscrolled.
///
......@@ -253,8 +254,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
/// `double.infinity`, it will not be respected if
/// [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite.
///
/// Mustn't be null and the value has to be within the range of 0 to
/// [minOverscrollLength], inclusive. Defaults to 18.0.
/// Mustn't be null and the value has to be greater or equal to
/// [minOverscrollLength], which in turn is >= 0. Defaults to 18.0.
double get minLength => _minLength;
double _minLength;
set minLength(double value) {
......@@ -266,7 +267,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners();
}
/// The preferred smallest size the scrollbar can shrink to when viewport is
/// The preferred smallest size the scrollbar thumb can shrink to when viewport is
/// overscrolled.
///
/// When overscrolling, the size of the scrollbar may shrink to a smaller size
......@@ -275,7 +276,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
/// the [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite.
///
/// The value is less than or equal to [minLength] and greater than or equal to 0.
/// If unspecified or set to null, it will defaults to the value of [minLength].
/// When null, it will default to the value of [minLength].
double get minOverscrollLength => _minOverscrollLength;
double _minOverscrollLength;
set minOverscrollLength(double value) {
......@@ -857,6 +858,8 @@ class RawScrollbar extends StatefulWidget {
this.radius,
this.thickness,
this.thumbColor,
this.minThumbLength = _kMinThumbExtent,
this.minOverscrollLength,
this.fadeDuration = _kScrollbarFadeDuration,
this.timeToFade = _kScrollbarTimeToFade,
this.pressDuration = Duration.zero,
......@@ -864,11 +867,17 @@ class RawScrollbar extends StatefulWidget {
this.interactive,
this.scrollbarOrientation,
this.mainAxisMargin = 0.0,
this.crossAxisMargin = 0.0
}) : assert(child != null),
assert(minThumbLength != null),
assert(minThumbLength >= 0),
assert(minOverscrollLength == null || minOverscrollLength <= minThumbLength),
assert(minOverscrollLength == null || minOverscrollLength >= 0),
assert(fadeDuration != null),
assert(timeToFade != null),
assert(pressDuration != null),
assert(mainAxisMargin != null),
assert(crossAxisMargin != null),
super(key: key);
/// {@template flutter.widgets.Scrollbar.child}
......@@ -1030,6 +1039,34 @@ class RawScrollbar extends StatefulWidget {
/// If null, defaults to Color(0x66BCBCBC).
final Color? thumbColor;
/// The preferred smallest size the scrollbar thumb can shrink to when the total
/// scrollable extent is large, the current visible viewport is small, and the
/// viewport is not overscrolled.
///
/// The size of the scrollbar's thumb may shrink to a smaller size than [minThumbLength]
/// to fit in the available paint area (e.g., when [minThumbLength] is greater
/// than [ScrollMetrics.viewportDimension] and [mainAxisMargin] combined).
///
/// Mustn't be null and the value has to be greater or equal to
/// [minOverscrollLength], which in turn is >= 0. Defaults to 18.0.
final double minThumbLength;
/// The preferred smallest size the scrollbar thumb can shrink to when viewport is
/// overscrolled.
///
/// When overscrolling, the size of the scrollbar's thumb may shrink to a smaller size
/// than [minOverscrollLength] to fit in the available paint area (e.g., when
/// [minOverscrollLength] is greater than [ScrollMetrics.viewportDimension] and
/// [mainAxisMargin] combined).
///
/// Overscrolling can be made possible by setting the `physics` property
/// of the `child` Widget to a `BouncingScrollPhysics`, which is a special
/// `ScrollPhysics` that allows overscrolling.
///
/// The value is less than or equal to [minThumbLength] and greater than or equal to 0.
/// When null, it will default to the value of [minThumbLength].
final double? minOverscrollLength;
/// The [Duration] of the fade animation.
///
/// Cannot be null, defaults to a [Duration] of 300 milliseconds.
......@@ -1085,6 +1122,12 @@ class RawScrollbar extends StatefulWidget {
/// Mustn't be null and defaults to 0.
final double mainAxisMargin;
/// Distance from the scrollbar thumb side to the nearest cross axis edge
/// in logical pixels.
///
/// Must not be null and defaults to 0.
final double crossAxisMargin;
@override
RawScrollbarState<RawScrollbar> createState() => RawScrollbarState<RawScrollbar>();
}
......@@ -1154,10 +1197,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
);
scrollbarPainter = ScrollbarPainter(
color: widget.thumbColor ?? const Color(0x66BCBCBC),
minLength: widget.minThumbLength,
minOverscrollLength: widget.minOverscrollLength ?? widget.minThumbLength,
thickness: widget.thickness ?? _kScrollbarThickness,
fadeoutOpacityAnimation: _fadeoutOpacityAnimation,
scrollbarOrientation: widget.scrollbarOrientation,
mainAxisMargin: widget.mainAxisMargin,
crossAxisMargin: widget.crossAxisMargin
);
}
......@@ -1294,7 +1340,10 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
..radius = widget.radius
..padding = MediaQuery.of(context).padding
..scrollbarOrientation = widget.scrollbarOrientation
..mainAxisMargin = widget.mainAxisMargin;
..mainAxisMargin = widget.mainAxisMargin
..crossAxisMargin = widget.crossAxisMargin
..minLength = widget.minThumbLength
..minOverscrollLength = widget.minOverscrollLength ?? widget.minThumbLength;
}
@override
......
......@@ -1482,4 +1482,87 @@ void main() {
..rect(rect: const Rect.fromLTRB(794.0, 10.0, 800.0, 358.0))
);
});
testWidgets('minThumbLength property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: RawScrollbar(
controller: scrollController,
minThumbLength: 21,
minOverscrollLength: 8,
isAlwaysShown: true,
child: SingleChildScrollView(
controller: scrollController,
child: const SizedBox(width: 1000.0, height: 50000.0),
),
),
)));
await tester.pumpAndSettle();
expect(
find.byType(RawScrollbar),
paints
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 600.0)) // track
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 21.0))); // thumb
});
testWidgets('crossAxisMargin property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: RawScrollbar(
controller: scrollController,
crossAxisMargin: 30,
isAlwaysShown: true,
child: SingleChildScrollView(
controller: scrollController,
child: const SizedBox(width: 1000.0, height: 1000.0),
),
),
)));
await tester.pumpAndSettle();
expect(
find.byType(RawScrollbar),
paints
..rect(rect: const Rect.fromLTRB(734.0, 0.0, 800.0, 600.0))
..rect(rect: const Rect.fromLTRB(764.0, 0.0, 770.0, 360.0)));
});
testWidgets('minOverscrollLength property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: RawScrollbar(
controller: scrollController,
isAlwaysShown: true,
minOverscrollLength: 8.0,
minThumbLength: 36.0,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
controller: scrollController,
child: const SizedBox(height: 10000),
)
),
)
)
);
await tester.pumpAndSettle();
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(RawScrollbar)));
await gesture.moveBy(const Offset(0, 1000));
await tester.pump();
expect(
find.byType(RawScrollbar),
paints
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 600.0))
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 8.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