From 48d5fcabbd805a622b74af2d2671ff0c845abdcd Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Tue, 11 Feb 2020 12:52:53 -0800 Subject: [PATCH] evict _SliverFractionalPadding cache on constraint change (#50523) --- .../flutter/lib/src/widgets/sliver_fill.dart | 6 ++- .../flutter/test/widgets/page_view_test.dart | 42 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/widgets/sliver_fill.dart b/packages/flutter/lib/src/widgets/sliver_fill.dart index 6d9fcae4477..6261c196d56 100644 --- a/packages/flutter/lib/src/widgets/sliver_fill.dart +++ b/packages/flutter/lib/src/widgets/sliver_fill.dart @@ -122,6 +122,8 @@ class _RenderSliverFractionalPadding extends RenderSliverEdgeInsetsPadding { assert(viewportFraction >= 0), _viewportFraction = viewportFraction; + SliverConstraints _lastResolvedConstraints; + double get viewportFraction => _viewportFraction; double _viewportFraction; set viewportFraction(double newValue) { @@ -142,10 +144,12 @@ class _RenderSliverFractionalPadding extends RenderSliverEdgeInsetsPadding { } void _resolve() { - if (_resolvedPadding != null) + if (_resolvedPadding != null && _lastResolvedConstraints == constraints) return; + assert(constraints.axis != null); final double paddingValue = constraints.viewportMainAxisExtent * viewportFraction; + _lastResolvedConstraints = constraints; switch (constraints.axis) { case Axis.horizontal: _resolvedPadding = EdgeInsets.symmetric(horizontal: paddingValue); diff --git a/packages/flutter/test/widgets/page_view_test.dart b/packages/flutter/test/widgets/page_view_test.dart index b2ba9365d71..6f47ddc375c 100644 --- a/packages/flutter/test/widgets/page_view_test.dart +++ b/packages/flutter/test/widgets/page_view_test.dart @@ -682,6 +682,48 @@ void main() { } }); + testWidgets('the current item remains centered on constraint change', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/50505. + final PageController controller = PageController( + initialPage: kStates.length - 1, + viewportFraction: 0.5, + ); + + Widget build(Size size) { + return Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: SizedBox.fromSize( + size: size, + child: PageView( + children: kStates.map((String state) => Text(state)).toList(), + controller: controller, + onPageChanged: (int page) { }, + ), + ), + ), + ); + } + + // Verifies that the last item is centered on screen. + void verifyCentered() { + expect( + tester.getCenter(find.text(kStates.last)), + offsetMoreOrLessEquals(const Offset(400, 300)), + ); + } + + await tester.pumpWidget(build(const Size(300, 300))); + await tester.pumpAndSettle(); + + verifyCentered(); + + await tester.pumpWidget(build(const Size(200, 300))); + await tester.pumpAndSettle(); + + verifyCentered(); + }); + testWidgets('PageView does not report page changed on overscroll', (WidgetTester tester) async { final PageController controller = PageController( initialPage: kStates.length - 1,