Apply physics boundary to scrollbar dragging (#72741)
This commit is contained in:
parent
3335bcbe40
commit
d4da441e53
@ -20,6 +20,7 @@ import 'primary_scroll_controller.dart';
|
||||
import 'scroll_controller.dart';
|
||||
import 'scroll_metrics.dart';
|
||||
import 'scroll_notification.dart';
|
||||
import 'scroll_position.dart';
|
||||
import 'scrollable.dart';
|
||||
import 'ticker_provider.dart';
|
||||
|
||||
@ -879,13 +880,18 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||
|
||||
void _updateScrollPosition(double primaryDelta) {
|
||||
assert(_currentController != null);
|
||||
final ScrollPosition position = _currentController!.position;
|
||||
|
||||
// Convert primaryDelta, the amount that the scrollbar moved since the last
|
||||
// time _dragScrollbar was called, into the coordinate space of the scroll
|
||||
// time _updateScrollPosition was called, into the coordinate space of the scroll
|
||||
// position, and jump to that position.
|
||||
final double scrollOffsetLocal = scrollbarPainter.getTrackToScroll(primaryDelta);
|
||||
final double scrollOffsetGlobal = scrollOffsetLocal + _currentController!.position.pixels;
|
||||
_currentController!.position.jumpTo(scrollOffsetGlobal);
|
||||
final double scrollOffsetGlobal = scrollOffsetLocal + position.pixels;
|
||||
if (scrollOffsetGlobal != position.pixels) {
|
||||
// Ensure we don't drag into overscroll if the physics do not allow it.
|
||||
final double physicsAdjustment = position.physics.applyBoundaryConditions(position, scrollOffsetGlobal);
|
||||
position.jumpTo(scrollOffsetGlobal - physicsAdjustment);
|
||||
}
|
||||
}
|
||||
|
||||
void _maybeStartFadeoutTimer() {
|
||||
|
@ -752,4 +752,56 @@ void main() {
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Scrollbar thumb cannot be dragged into overscroll if the physics do not allow', (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(
|
||||
isAlwaysShown: true,
|
||||
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
|
||||
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 600.0))
|
||||
..rect(
|
||||
rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 90.0),
|
||||
color: const Color(0x66BCBCBC),
|
||||
),
|
||||
);
|
||||
|
||||
// Try to drag the thumb into overscroll.
|
||||
const double scrollAmount = -10.0;
|
||||
final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
|
||||
await tester.pumpAndSettle();
|
||||
await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// The physics should not have allowed us to enter overscroll.
|
||||
expect(scrollController.offset, 0.0);
|
||||
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, 90.0),
|
||||
color: const Color(0x66BCBCBC),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user