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 { ...@@ -196,7 +196,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners(); 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. /// Must not be null and defaults to 0.
double get crossAxisMargin => _crossAxisMargin; double get crossAxisMargin => _crossAxisMargin;
...@@ -244,7 +245,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -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 /// scrollable extent is large, the current visible viewport is small, and the
/// viewport is not overscrolled. /// viewport is not overscrolled.
/// ///
...@@ -253,8 +254,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -253,8 +254,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
/// `double.infinity`, it will not be respected if /// `double.infinity`, it will not be respected if
/// [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite. /// [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite.
/// ///
/// Mustn't be null and the value has to be within the range of 0 to /// Mustn't be null and the value has to be greater or equal to
/// [minOverscrollLength], inclusive. Defaults to 18.0. /// [minOverscrollLength], which in turn is >= 0. Defaults to 18.0.
double get minLength => _minLength; double get minLength => _minLength;
double _minLength; double _minLength;
set minLength(double value) { set minLength(double value) {
...@@ -266,7 +267,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -266,7 +267,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
notifyListeners(); 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. /// overscrolled.
/// ///
/// When overscrolling, the size of the scrollbar may shrink to a smaller size /// When overscrolling, the size of the scrollbar may shrink to a smaller size
...@@ -275,7 +276,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { ...@@ -275,7 +276,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
/// the [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite. /// the [ScrollMetrics.viewportDimension] and [mainAxisMargin] are finite.
/// ///
/// The value is less than or equal to [minLength] and greater than or equal to 0. /// 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 get minOverscrollLength => _minOverscrollLength;
double _minOverscrollLength; double _minOverscrollLength;
set minOverscrollLength(double value) { set minOverscrollLength(double value) {
...@@ -857,6 +858,8 @@ class RawScrollbar extends StatefulWidget { ...@@ -857,6 +858,8 @@ class RawScrollbar extends StatefulWidget {
this.radius, this.radius,
this.thickness, this.thickness,
this.thumbColor, this.thumbColor,
this.minThumbLength = _kMinThumbExtent,
this.minOverscrollLength,
this.fadeDuration = _kScrollbarFadeDuration, this.fadeDuration = _kScrollbarFadeDuration,
this.timeToFade = _kScrollbarTimeToFade, this.timeToFade = _kScrollbarTimeToFade,
this.pressDuration = Duration.zero, this.pressDuration = Duration.zero,
...@@ -864,11 +867,17 @@ class RawScrollbar extends StatefulWidget { ...@@ -864,11 +867,17 @@ class RawScrollbar extends StatefulWidget {
this.interactive, this.interactive,
this.scrollbarOrientation, this.scrollbarOrientation,
this.mainAxisMargin = 0.0, this.mainAxisMargin = 0.0,
this.crossAxisMargin = 0.0
}) : assert(child != null), }) : assert(child != null),
assert(minThumbLength != null),
assert(minThumbLength >= 0),
assert(minOverscrollLength == null || minOverscrollLength <= minThumbLength),
assert(minOverscrollLength == null || minOverscrollLength >= 0),
assert(fadeDuration != null), assert(fadeDuration != null),
assert(timeToFade != null), assert(timeToFade != null),
assert(pressDuration != null), assert(pressDuration != null),
assert(mainAxisMargin != null), assert(mainAxisMargin != null),
assert(crossAxisMargin != null),
super(key: key); super(key: key);
/// {@template flutter.widgets.Scrollbar.child} /// {@template flutter.widgets.Scrollbar.child}
...@@ -1030,6 +1039,34 @@ class RawScrollbar extends StatefulWidget { ...@@ -1030,6 +1039,34 @@ class RawScrollbar extends StatefulWidget {
/// If null, defaults to Color(0x66BCBCBC). /// If null, defaults to Color(0x66BCBCBC).
final Color? thumbColor; 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. /// The [Duration] of the fade animation.
/// ///
/// Cannot be null, defaults to a [Duration] of 300 milliseconds. /// Cannot be null, defaults to a [Duration] of 300 milliseconds.
...@@ -1085,6 +1122,12 @@ class RawScrollbar extends StatefulWidget { ...@@ -1085,6 +1122,12 @@ class RawScrollbar extends StatefulWidget {
/// Mustn't be null and defaults to 0. /// Mustn't be null and defaults to 0.
final double mainAxisMargin; 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 @override
RawScrollbarState<RawScrollbar> createState() => RawScrollbarState<RawScrollbar>(); RawScrollbarState<RawScrollbar> createState() => RawScrollbarState<RawScrollbar>();
} }
...@@ -1154,10 +1197,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv ...@@ -1154,10 +1197,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
); );
scrollbarPainter = ScrollbarPainter( scrollbarPainter = ScrollbarPainter(
color: widget.thumbColor ?? const Color(0x66BCBCBC), color: widget.thumbColor ?? const Color(0x66BCBCBC),
minLength: widget.minThumbLength,
minOverscrollLength: widget.minOverscrollLength ?? widget.minThumbLength,
thickness: widget.thickness ?? _kScrollbarThickness, thickness: widget.thickness ?? _kScrollbarThickness,
fadeoutOpacityAnimation: _fadeoutOpacityAnimation, fadeoutOpacityAnimation: _fadeoutOpacityAnimation,
scrollbarOrientation: widget.scrollbarOrientation, scrollbarOrientation: widget.scrollbarOrientation,
mainAxisMargin: widget.mainAxisMargin, mainAxisMargin: widget.mainAxisMargin,
crossAxisMargin: widget.crossAxisMargin
); );
} }
...@@ -1294,7 +1340,10 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv ...@@ -1294,7 +1340,10 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
..radius = widget.radius ..radius = widget.radius
..padding = MediaQuery.of(context).padding ..padding = MediaQuery.of(context).padding
..scrollbarOrientation = widget.scrollbarOrientation ..scrollbarOrientation = widget.scrollbarOrientation
..mainAxisMargin = widget.mainAxisMargin; ..mainAxisMargin = widget.mainAxisMargin
..crossAxisMargin = widget.crossAxisMargin
..minLength = widget.minThumbLength
..minOverscrollLength = widget.minOverscrollLength ?? widget.minThumbLength;
} }
@override @override
......
...@@ -1482,4 +1482,87 @@ void main() { ...@@ -1482,4 +1482,87 @@ void main() {
..rect(rect: const Rect.fromLTRB(794.0, 10.0, 800.0, 358.0)) ..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