diff --git a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart index 91975d76fe4..9bc80478314 100644 --- a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; +import 'primary_scroll_controller.dart'; import 'scroll_controller.dart'; import 'scroll_physics.dart'; import 'scrollable.dart'; @@ -42,11 +43,17 @@ class SingleChildScrollView extends StatelessWidget { this.scrollDirection: Axis.vertical, this.reverse: false, this.padding, + this.primary: false, this.physics, this.controller, this.child, }) : super(key: key) { assert(scrollDirection != null); + assert(primary != null); + assert(controller == null || !primary, + 'Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. ' + 'You cannot both set primary to true and pass an explicit controller.' + ); } final Axis scrollDirection; @@ -57,6 +64,8 @@ class SingleChildScrollView extends StatelessWidget { final ScrollController controller; + final bool primary; + final ScrollPhysics physics; final Widget child; @@ -80,7 +89,7 @@ class SingleChildScrollView extends StatelessWidget { contents = new Padding(padding: padding, child: contents); return new Scrollable( axisDirection: axisDirection, - controller: controller, + controller: controller ?? (primary ? PrimaryScrollController.of(context) : null), physics: physics, viewportBuilder: (BuildContext context, ViewportOffset offset) { return new _SingleChildViewport( diff --git a/packages/flutter/test/widgets/single_child_scroll_view_test.dart b/packages/flutter/test/widgets/single_child_scroll_view_test.dart index b5a640a5437..5ae04f25c97 100644 --- a/packages/flutter/test/widgets/single_child_scroll_view_test.dart +++ b/packages/flutter/test/widgets/single_child_scroll_view_test.dart @@ -76,6 +76,26 @@ void main() { expect(scrollable.position, const isInstanceOf()); }); + testWidgets('Sets PrimaryScrollController when primary', (WidgetTester tester) async { + ScrollController primaryScrollController = new ScrollController(); + await tester.pumpWidget(new PrimaryScrollController( + controller: primaryScrollController, + child: new SingleChildScrollView( + primary: true, + child: new Container( + height: 2000.0, + decoration: const BoxDecoration( + backgroundColor: const Color(0xFF00FF00), + ), + ), + ), + )); + + Scrollable scrollable = tester.widget(find.byType(Scrollable)); + expect(scrollable.controller, primaryScrollController); + }); + + testWidgets('Changing scroll controller inside dirty layout builder does not assert', (WidgetTester tester) async { ScrollController controller = new ScrollController();