diff --git a/packages/flutter/lib/src/widgets/page_view.dart b/packages/flutter/lib/src/widgets/page_view.dart index 2a31d8e3e4..ed54495455 100644 --- a/packages/flutter/lib/src/widgets/page_view.dart +++ b/packages/flutter/lib/src/widgets/page_view.dart @@ -383,13 +383,16 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri @override double? get page { + if (!hasPixels) { + return null; + } assert( - !hasPixels || hasContentDimensions, + hasContentDimensions || !haveDimensions, 'Page value is only available after content dimensions are established.', ); - return !hasPixels || !hasContentDimensions - ? null - : _cachedPage ?? getPageFromPixels(clampDouble(pixels, minScrollExtent, maxScrollExtent), viewportDimension); + return hasContentDimensions || haveDimensions + ? _cachedPage ?? getPageFromPixels(clampDouble(pixels, minScrollExtent, maxScrollExtent), viewportDimension) + : null; } @override diff --git a/packages/flutter/test/widgets/page_view_test.dart b/packages/flutter/test/widgets/page_view_test.dart index aa6d305a30..78e6fd8cbf 100644 --- a/packages/flutter/test/widgets/page_view_test.dart +++ b/packages/flutter/test/widgets/page_view_test.dart @@ -1372,4 +1372,45 @@ void main() { await tester.pumpWidget(createPageView(null)); }); }); + + testWidgets('Get the page value before the content dimension is determined,do not throw an assertion and return null', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/146986. + final PageController controller = PageController(); + late String currentPage; + addTearDown(controller.dispose); + await tester.pumpWidget(MaterialApp( + home: Material( + child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) { + return Scaffold( + body: PageView( + controller: controller, + children: [ + Builder( + builder: (BuildContext context) { + currentPage = controller.page == null ? 'null' : 'not empty'; + return Center(child: Text(currentPage)); + }, + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + setState(() {}); + }, + ), + ); + }), + ), + )); + expect(find.text('null'), findsOneWidget); + expect(find.text('not empty'), findsNothing); + expect(currentPage, 'null'); + + await tester.tap(find.byType(FloatingActionButton)); + await tester.pump(); + currentPage = controller.page == null ? 'null' : 'not empty'; + expect(find.text('not empty'), findsOneWidget); + expect(find.text('null'), findsNothing); + expect(currentPage, 'not empty'); + }); }