Skip to content

Commit 691a18d

Browse files
authored
[CupertinoActionSheet] Fix overflow of the overscroll section when the user scrolls far (#149542)
When I implemented flutter/flutter#149334, there was a bug that if the actions section is overscrolled for too far (typically due to a fling), the overscroll background might be so long that it overflows the actions section. This PR fixes this bug.
1 parent e02d29d commit 691a18d

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

packages/flutter/lib/src/cupertino/dialog.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,8 +964,16 @@ class _ActionSheetMainSheetState extends State<_ActionSheetMainSheet> {
964964
bool _onScrollUpdate(ScrollUpdateNotification notification) {
965965
final ScrollMetrics metrics = notification.metrics;
966966
setState(() {
967-
_topOverscroll = math.max(metrics.minScrollExtent - metrics.pixels, 0);
968-
_bottomOverscroll = math.max(metrics.pixels - metrics.maxScrollExtent, 0);
967+
// The sizes of the overscroll should not be longer than the height of the
968+
// actions section.
969+
_topOverscroll = math.min(
970+
math.max(metrics.minScrollExtent - metrics.pixels, 0),
971+
metrics.viewportDimension,
972+
);
973+
_bottomOverscroll = math.min(
974+
math.max(metrics.pixels - metrics.maxScrollExtent, 0),
975+
metrics.viewportDimension,
976+
);
969977
});
970978
return false;
971979
}

packages/flutter/test/cupertino/action_sheet_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,48 @@ void main() {
489489
await gesture.up();
490490
});
491491

492+
testWidgets('Actions section correctly renders overscrolls with very far scrolls', (WidgetTester tester) async {
493+
// When the scroll is really far, the overscroll might be longer than the
494+
// actions section, causing overflow if not controlled.
495+
final ScrollController actionScrollController = ScrollController();
496+
addTearDown(actionScrollController.dispose);
497+
await tester.pumpWidget(
498+
createAppWithButtonThatLaunchesActionSheet(
499+
Builder(builder: (BuildContext context) {
500+
return CupertinoActionSheet(
501+
message: Text('message' * 300),
502+
actions: List<Widget>.generate(4, (int i) =>
503+
CupertinoActionSheetAction(
504+
onPressed: () {},
505+
child: Text('Button $i'),
506+
),
507+
),
508+
);
509+
}),
510+
),
511+
);
512+
513+
await tester.tap(find.text('Go'));
514+
await tester.pumpAndSettle();
515+
516+
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Button 0')));
517+
await tester.pumpAndSettle();
518+
await gesture.moveBy(const Offset(0, 40)); // A short drag to start the gesture.
519+
await tester.pumpAndSettle();
520+
// The drag is far enough to make the overscroll longer than the section.
521+
await gesture.moveBy(const Offset(0, 1000));
522+
await tester.pump();
523+
// The buttons should be out of the screen
524+
expect(
525+
tester.getTopLeft(find.text('Button 0')).dy,
526+
greaterThan(tester.getBottomLeft(find.byType(CupertinoActionSheet)).dy)
527+
);
528+
await expectLater(
529+
find.byType(CupertinoActionSheet),
530+
matchesGoldenFile('cupertinoActionSheet.long-overscroll.0.png'),
531+
);
532+
});
533+
492534
testWidgets('Tap on button calls onPressed', (WidgetTester tester) async {
493535
bool wasPressed = false;
494536
await tester.pumpWidget(

0 commit comments

Comments
 (0)