mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
This commit is contained in:
parent
913c57021d
commit
58c4bd1063
|
@ -276,21 +276,14 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|
||||||
Rect? _trackRect;
|
Rect? _trackRect;
|
||||||
late double _thumbOffset;
|
late double _thumbOffset;
|
||||||
|
|
||||||
/// Update with new [ScrollMetrics]. If the metrics change, the scrollbar will
|
/// Update with new [ScrollMetrics]. The scrollbar will show and redraw itself
|
||||||
/// show and redraw itself based on these new metrics.
|
/// based on these new metrics.
|
||||||
///
|
///
|
||||||
/// The scrollbar will remain on screen.
|
/// The scrollbar will remain on screen.
|
||||||
void update(
|
void update(
|
||||||
ScrollMetrics metrics,
|
ScrollMetrics metrics,
|
||||||
AxisDirection axisDirection,
|
AxisDirection axisDirection,
|
||||||
) {
|
) {
|
||||||
if (_lastMetrics != null &&
|
|
||||||
_lastMetrics!.extentBefore == metrics.extentBefore &&
|
|
||||||
_lastMetrics!.extentInside == metrics.extentInside &&
|
|
||||||
_lastMetrics!.extentAfter == metrics.extentAfter &&
|
|
||||||
_lastAxisDirection == axisDirection)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_lastMetrics = metrics;
|
_lastMetrics = metrics;
|
||||||
_lastAxisDirection = axisDirection;
|
_lastAxisDirection = axisDirection;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -937,17 +930,16 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_maybeRequestEmptyScrollEvent();
|
_maybeTriggerScrollbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Waits one frame and cause an empty scroll event (zero delta pixels).
|
// Waits one frame and cause an empty scroll event (zero delta pixels).
|
||||||
//
|
//
|
||||||
// This allows the thumb to show immediately when isAlwaysShown is true.
|
// This allows the thumb to show immediately when isAlwaysShown is true.
|
||||||
// A scroll event is required in order to paint the thumb.
|
// A scroll event is required in order to paint the thumb.
|
||||||
void _maybeRequestEmptyScrollEvent() {
|
void _maybeTriggerScrollbar() {
|
||||||
if (!showScrollbar)
|
|
||||||
return;
|
|
||||||
WidgetsBinding.instance!.addPostFrameCallback((Duration duration) {
|
WidgetsBinding.instance!.addPostFrameCallback((Duration duration) {
|
||||||
|
if (showScrollbar) {
|
||||||
_fadeoutTimer?.cancel();
|
_fadeoutTimer?.cancel();
|
||||||
// Wait one frame and cause an empty scroll event. This allows the
|
// Wait one frame and cause an empty scroll event. This allows the
|
||||||
// thumb to show immediately when isAlwaysShown is true. A scroll
|
// thumb to show immediately when isAlwaysShown is true. A scroll
|
||||||
|
@ -1021,6 +1013,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
scrollController!.position.didUpdateScrollPositionBy(0);
|
scrollController!.position.didUpdateScrollPositionBy(0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,16 +1035,15 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(T oldWidget) {
|
void didUpdateWidget(T oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
// If `isAlwaysShown` is true and does not change,
|
if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
|
||||||
// it may be necessary to trigger a scroll event to show or hide the bar when the
|
|
||||||
// scrollable widget viewport size changed.
|
|
||||||
if (widget.isAlwaysShown == true) {
|
if (widget.isAlwaysShown == true) {
|
||||||
_maybeRequestEmptyScrollEvent();
|
_maybeTriggerScrollbar();
|
||||||
_fadeoutAnimationController.animateTo(1.0);
|
_fadeoutAnimationController.animateTo(1.0);
|
||||||
} else if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
|
} else {
|
||||||
_fadeoutAnimationController.reverse();
|
_fadeoutAnimationController.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _updateScrollPosition(double primaryDelta) {
|
void _updateScrollPosition(double primaryDelta) {
|
||||||
assert(_currentController != null);
|
assert(_currentController != null);
|
||||||
|
@ -1211,19 +1203,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
final ScrollMetrics metrics = notification.metrics;
|
final ScrollMetrics metrics = notification.metrics;
|
||||||
if (metrics.maxScrollExtent <= metrics.minScrollExtent) {
|
if (metrics.maxScrollExtent <= metrics.minScrollExtent)
|
||||||
// Hide the bar when the Scrollable widget has no space to scroll.
|
|
||||||
if (_fadeoutAnimationController.status != AnimationStatus.dismissed
|
|
||||||
&& _fadeoutAnimationController.status != AnimationStatus.reverse)
|
|
||||||
_fadeoutAnimationController.reverse();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (notification is ScrollUpdateNotification ||
|
if (notification is ScrollUpdateNotification ||
|
||||||
notification is OverscrollNotification) {
|
notification is OverscrollNotification) {
|
||||||
// Any movements always makes the scrollbar start showing up.
|
// Any movements always makes the scrollbar start showing up.
|
||||||
if (_fadeoutAnimationController.status != AnimationStatus.forward
|
if (_fadeoutAnimationController.status != AnimationStatus.forward)
|
||||||
&& _fadeoutAnimationController.status != AnimationStatus.completed)
|
|
||||||
_fadeoutAnimationController.forward();
|
_fadeoutAnimationController.forward();
|
||||||
|
|
||||||
_fadeoutTimer?.cancel();
|
_fadeoutTimer?.cancel();
|
||||||
|
|
|
@ -1152,35 +1152,4 @@ void main() {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('The bar can show or hide when the viewport size change', (WidgetTester tester) async {
|
|
||||||
final ScrollController scrollController = ScrollController();
|
|
||||||
Widget buildFrame(double height) {
|
|
||||||
return Directionality(
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
child: MediaQuery(
|
|
||||||
data: const MediaQueryData(),
|
|
||||||
child: RawScrollbar(
|
|
||||||
controller: scrollController,
|
|
||||||
isAlwaysShown: true,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
controller: scrollController,
|
|
||||||
child: SizedBox(width: double.infinity, height: height)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await tester.pumpWidget(buildFrame(600.0));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Not shown.
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(600.1));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(find.byType(RawScrollbar), paints..rect()..rect()); // Show the bar.
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(600.0));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Hide the bar.
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue