Skip to content

Commit d595e98

Browse files
authored
Fix PageController throws when changing page before viewPortDimensions are set (#153017)
## Description This PR fixes `PageController` throwing when using `jumpToPage` or `animateToPage` to switch page before the viewport dimensions were retrieved. Solution based on flutter/flutter#152947 (comment). ## Related Issue Fixes flutter/flutter#86222. Fixes flutter/flutter#152079 ## Tests Adds 2 tests.
1 parent 2ff7fe9 commit d595e98

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

packages/flutter/lib/src/widgets/page_view.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ class PageController extends ScrollController {
200200
return Future<void>.value();
201201
}
202202

203+
if (!position.hasViewportDimension) {
204+
position._pageToUseOnStartup = page.toDouble();
205+
return Future<void>.value();
206+
}
207+
203208
return position.animateTo(
204209
position.getPixelsFromPage(page.toDouble()),
205210
duration: duration,
@@ -218,6 +223,11 @@ class PageController extends ScrollController {
218223
return;
219224
}
220225

226+
if (!position.hasViewportDimension) {
227+
position._pageToUseOnStartup = page.toDouble();
228+
return;
229+
}
230+
221231
position.jumpTo(position.getPixelsFromPage(page.toDouble()));
222232
}
223233

packages/flutter/test/widgets/page_view_test.dart

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,4 +1413,62 @@ void main() {
14131413
expect(find.text('null'), findsNothing);
14141414
expect(currentPage, 'not empty');
14151415
});
1416+
1417+
testWidgets('Does not crash when calling jumpToPage before layout', (WidgetTester tester) async {
1418+
// Regression test for https://github.com/flutter/flutter/issues/86222.
1419+
final PageController controller = PageController();
1420+
addTearDown(controller.dispose);
1421+
1422+
await tester.pumpWidget(MaterialApp(
1423+
home: Scaffold(
1424+
body: Navigator(
1425+
onDidRemovePage: (Page<Object?> page) {},
1426+
pages: <Page<void>>[
1427+
MaterialPage<void>(child: Scaffold(
1428+
body: PageView(
1429+
controller: controller,
1430+
children: const <Widget>[
1431+
Scaffold(body: Text('One')),
1432+
Scaffold(body: Text('Two')),
1433+
],
1434+
),
1435+
)),
1436+
const MaterialPage<void>(child: Scaffold()),
1437+
],
1438+
),
1439+
)
1440+
));
1441+
1442+
controller.jumpToPage(1);
1443+
expect(tester.takeException(), null);
1444+
});
1445+
1446+
testWidgets('Does not crash when calling animateToPage before layout', (WidgetTester tester) async {
1447+
// Regression test for https://github.com/flutter/flutter/issues/86222.
1448+
final PageController controller = PageController();
1449+
addTearDown(controller.dispose);
1450+
1451+
await tester.pumpWidget(MaterialApp(
1452+
home: Scaffold(
1453+
body: Navigator(
1454+
onDidRemovePage: (Page<Object?> page) {},
1455+
pages: <Page<void>>[
1456+
MaterialPage<void>(child: Scaffold(
1457+
body: PageView(
1458+
controller: controller,
1459+
children: const <Widget>[
1460+
Scaffold(body: Text('One')),
1461+
Scaffold(body: Text('Two')),
1462+
],
1463+
),
1464+
)),
1465+
const MaterialPage<void>(child: Scaffold()),
1466+
],
1467+
),
1468+
)
1469+
));
1470+
1471+
controller.animateToPage(1, duration: const Duration(milliseconds: 50), curve: Curves.bounceIn);
1472+
expect(tester.takeException(), null);
1473+
});
14161474
}

0 commit comments

Comments
 (0)