ScrollController should notify when its offset changes (#8768)

This change make it easier to track the position of the scroll view without
having to worry about the position object changing out from under the
controller.
This commit is contained in:
Adam Barth
2017-03-14 14:07:35 -07:00
committed by GitHub
parent fd51093146
commit 146fc617ca
2 changed files with 40 additions and 1 deletions

View File

@@ -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,

View File

@@ -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<double> log = <double>[];
controller.addListener(() {
log.add(controller.offset);
});
await tester.pumpWidget(new ListView(
controller: controller,
children: kStates.map<Widget>((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(<double>[ 250.0 ]));
log.clear();
controller.dispose();
await tester.drag(find.byType(ListView), const Offset(0.0, -130.0));
expect(log, isEmpty);
});
}