Skip to content

Commit

Permalink
[CupertinoActionSheet] Fix overflow of the overscroll section when th…
Browse files Browse the repository at this point in the history
…e user scrolls far (flutter#149542)

When I implemented 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.
  • Loading branch information
dkwingsmt authored Jun 3, 2024
1 parent e02d29d commit 691a18d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
12 changes: 10 additions & 2 deletions packages/flutter/lib/src/cupertino/dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -964,8 +964,16 @@ class _ActionSheetMainSheetState extends State<_ActionSheetMainSheet> {
bool _onScrollUpdate(ScrollUpdateNotification notification) {
final ScrollMetrics metrics = notification.metrics;
setState(() {
_topOverscroll = math.max(metrics.minScrollExtent - metrics.pixels, 0);
_bottomOverscroll = math.max(metrics.pixels - metrics.maxScrollExtent, 0);
// The sizes of the overscroll should not be longer than the height of the
// actions section.
_topOverscroll = math.min(
math.max(metrics.minScrollExtent - metrics.pixels, 0),
metrics.viewportDimension,
);
_bottomOverscroll = math.min(
math.max(metrics.pixels - metrics.maxScrollExtent, 0),
metrics.viewportDimension,
);
});
return false;
}
Expand Down
42 changes: 42 additions & 0 deletions packages/flutter/test/cupertino/action_sheet_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,48 @@ void main() {
await gesture.up();
});

testWidgets('Actions section correctly renders overscrolls with very far scrolls', (WidgetTester tester) async {
// When the scroll is really far, the overscroll might be longer than the
// actions section, causing overflow if not controlled.
final ScrollController actionScrollController = ScrollController();
addTearDown(actionScrollController.dispose);
await tester.pumpWidget(
createAppWithButtonThatLaunchesActionSheet(
Builder(builder: (BuildContext context) {
return CupertinoActionSheet(
message: Text('message' * 300),
actions: List<Widget>.generate(4, (int i) =>
CupertinoActionSheetAction(
onPressed: () {},
child: Text('Button $i'),
),
),
);
}),
),
);

await tester.tap(find.text('Go'));
await tester.pumpAndSettle();

final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Button 0')));
await tester.pumpAndSettle();
await gesture.moveBy(const Offset(0, 40)); // A short drag to start the gesture.
await tester.pumpAndSettle();
// The drag is far enough to make the overscroll longer than the section.
await gesture.moveBy(const Offset(0, 1000));
await tester.pump();
// The buttons should be out of the screen
expect(
tester.getTopLeft(find.text('Button 0')).dy,
greaterThan(tester.getBottomLeft(find.byType(CupertinoActionSheet)).dy)
);
await expectLater(
find.byType(CupertinoActionSheet),
matchesGoldenFile('cupertinoActionSheet.long-overscroll.0.png'),
);
});

testWidgets('Tap on button calls onPressed', (WidgetTester tester) async {
bool wasPressed = false;
await tester.pumpWidget(
Expand Down

0 comments on commit 691a18d

Please sign in to comment.