[CupertinoActionSheet] Fix overflow of the overscroll section when the user scrolls far (#149542)

When I implemented https://github.com/flutter/flutter/pull/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.
This commit is contained in:
Tong Mu 2024-06-03 12:12:11 -07:00 committed by GitHub
parent e02d29d52e
commit 691a18df5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 2 deletions

View File

@ -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;
}

View File

@ -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(