diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index 59326257032..2fc43a44dd4 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -57,9 +57,9 @@ abstract class RenderAbstractViewport extends RenderObject { /// edge of the viewport as possible. If `alignment` is 0.5, the child must be /// positioned as close to the center of the viewport as possible. /// - /// The target might not be a direct child of this viewport but it must be a - /// descendant of the viewport and there must not be any other - /// [RenderAbstractViewport] objects between the target and this object. + /// The `target` might not be a direct child of this viewport but it must be a + /// descendant of the viewport. Other viewports in between this viewport and + /// the `target` will not be adjusted. /// /// This method assumes that the content of the viewport moves linearly, i.e. /// when the offset of the viewport is changed by x then `target` also moves @@ -585,26 +585,39 @@ abstract class RenderViewportBase slivers; + final ScrollController controllerX = ScrollController(initialScrollOffset: 0.0); + final ScrollController controllerY = ScrollController(initialScrollOffset: 0.0); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Container( + height: 200.0, + width: 200.0, + child: ListView( + controller: controllerY, + children: [ + Container( + height: 150.0, + ), + Container( + height: 100.0, + child: ListView( + physics: const PageScrollPhysics(), // Turns off `allowImplicitScrolling` + scrollDirection: Axis.horizontal, + controller: controllerX, + children: slivers = [ + Container( + width: 150.0, + ), + Container( + width: 150.0, + ), + ], + ), + ), + Container( + height: 150.0, + ), + ], + ), + ), + ), + ), + ); + + tester.renderObject(find.byWidget(slivers[1])).showOnScreen(); + await tester.pumpAndSettle(); + expect(controllerX.offset, 0.0); + expect(controllerY.offset, 50.0); + }); + + testWidgets('Nested Viewports showOnScreen on Sliver with allowImplicitScrolling=false for inner viewport', (WidgetTester tester) async { + Widget sliver; + final ScrollController controllerX = ScrollController(initialScrollOffset: 0.0); + final ScrollController controllerY = ScrollController(initialScrollOffset: 0.0); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: Container( + height: 200.0, + width: 200.0, + child: ListView( + controller: controllerY, + children: [ + Container( + height: 150.0, + ), + Container( + height: 100.0, + child: CustomScrollView( + physics: const PageScrollPhysics(), // Turns off `allowImplicitScrolling` + scrollDirection: Axis.horizontal, + controller: controllerX, + slivers: [ + SliverPadding( + padding: const EdgeInsets.all(25.0), + sliver: SliverToBoxAdapter( + child: Container( + width: 100.0, + ), + ), + ), + SliverPadding( + padding: const EdgeInsets.all(25.0), + sliver: sliver = SliverToBoxAdapter( + child: Container( + width: 100.0, + ), + ), + ), + ], + ), + ), + Container( + height: 150.0, + ), + ], + ), + ), + ), + ), + ); + + tester.renderObject(find.byWidget(sliver)).showOnScreen(); + await tester.pumpAndSettle(); + expect(controllerX.offset, 0.0); + expect(controllerY.offset, 25.0); + }); + testWidgets('Viewport showOnScreen with objects larger than viewport', (WidgetTester tester) async { List children; ScrollController controller;