diff --git a/packages/flutter/lib/src/widgets/scroll_controller.dart b/packages/flutter/lib/src/widgets/scroll_controller.dart index f6541e5d2f..96f73e4b46 100644 --- a/packages/flutter/lib/src/widgets/scroll_controller.dart +++ b/packages/flutter/lib/src/widgets/scroll_controller.dart @@ -5,11 +5,12 @@ import 'dart:async'; import 'package:flutter/animation.dart'; +import 'package:flutter/foundation.dart'; import 'package:meta/meta.dart'; import 'scroll_position.dart'; -class ScrollController { +class ScrollController extends ChangeNotifier { ScrollController({ this.initialScrollOffset: 0.0, }) { @@ -101,6 +102,7 @@ class ScrollController { void attach(ScrollPosition position) { assert(!_positions.contains(position)); _positions.add(position); + position.addListener(notifyListeners); } /// Unregister the given position with this controller. @@ -109,9 +111,17 @@ class ScrollController { /// controller will not manipulate the given position. void detach(ScrollPosition position) { assert(_positions.contains(position)); + position.removeListener(notifyListeners); _positions.remove(position); } + @override + void dispose() { + for (ScrollPosition position in _positions) + position.removeListener(notifyListeners); + super.dispose(); + } + static ScrollPosition createDefaultScrollPosition(ScrollPhysics physics, AbstractScrollState state, ScrollPosition oldPosition) { return new ScrollPosition( physics: physics, diff --git a/packages/flutter/test/widgets/scroll_controller_test.dart b/packages/flutter/test/widgets/scroll_controller_test.dart index b9a1d81de4..f935edcd57 100644 --- a/packages/flutter/test/widgets/scroll_controller_test.dart +++ b/packages/flutter/test/widgets/scroll_controller_test.dart @@ -230,4 +230,33 @@ void main() { controller.animateTo(1.0, duration: const Duration(seconds: 1), curve: Curves.linear); await tester.pumpAndSettle(); }); + + testWidgets('Scroll controllers notify when the position changes', (WidgetTester tester) async { + final ScrollController controller = new ScrollController(); + + final List log = []; + + controller.addListener(() { + log.add(controller.offset); + }); + + await tester.pumpWidget(new ListView( + controller: controller, + children: kStates.map((String state) { + return new Container(height: 200.0, child: new Text(state)); + }).toList(), + )); + + expect(log, isEmpty); + + await tester.drag(find.byType(ListView), const Offset(0.0, -250.0)); + + expect(log, equals([ 250.0 ])); + log.clear(); + + controller.dispose(); + + await tester.drag(find.byType(ListView), const Offset(0.0, -130.0)); + expect(log, isEmpty); + }); }