fix some DSS bugs (#112142)
diff --git a/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart b/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart
index a0658cc..c9c27cb 100644
--- a/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart
+++ b/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart
@@ -201,8 +201,12 @@
}
}
- void _detach() {
- _attachedController?.extent._currentSize.removeListener(notifyListeners);
+ void _detach({bool disposeExtent = false}) {
+ if (disposeExtent) {
+ _attachedController?.extent.dispose();
+ } else {
+ _attachedController?.extent._currentSize.removeListener(notifyListeners);
+ }
_attachedController = null;
}
@@ -593,6 +597,10 @@
return size / maxSize * availablePixels;
}
+ void dispose() {
+ _currentSize.dispose();
+ }
+
_DraggableSheetExtent copyWith({
required double minSize,
required double maxSize,
@@ -663,6 +671,10 @@
@override
void didUpdateWidget(covariant DraggableScrollableSheet oldWidget) {
super.didUpdateWidget(oldWidget);
+ if (widget.controller != oldWidget.controller) {
+ oldWidget.controller?._detach();
+ widget.controller?._attach(_scrollController);
+ }
_replaceExtent(oldWidget);
}
@@ -695,14 +707,14 @@
@override
void dispose() {
- widget.controller?._detach();
+ widget.controller?._detach(disposeExtent: true);
_scrollController.dispose();
super.dispose();
}
void _replaceExtent(covariant DraggableScrollableSheet oldWidget) {
final _DraggableSheetExtent previousExtent = _extent;
- _extent = _extent.copyWith(
+ _extent = previousExtent.copyWith(
minSize: widget.minChildSize,
maxSize: widget.maxChildSize,
snap: widget.snap,
@@ -716,6 +728,7 @@
// If an external facing controller was provided, let it know that the
// extent has been replaced.
widget.controller?._onExtentReplaced(previousExtent);
+ previousExtent.dispose();
if (widget.snap
&& (widget.snap != oldWidget.snap || widget.snapSizes != oldWidget.snapSizes)
&& _scrollController.hasClients
diff --git a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
index e7f0752..c18bd3a 100644
--- a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
+++ b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
@@ -1512,4 +1512,62 @@
// DraggableScrollableSheet has rebuilt, so expect the builder to be called.
expect(buildCount, 2);
});
+
+ testWidgets('DraggableScrollableSheet controller can be changed', (WidgetTester tester) async {
+ final DraggableScrollableController controller1 = DraggableScrollableController();
+ final DraggableScrollableController controller2 = DraggableScrollableController();
+ final List<double> loggedSizes = <double>[];
+
+ DraggableScrollableController controller = controller1;
+ await tester.pumpWidget(MaterialApp(
+ home: StatefulBuilder(
+ builder: (BuildContext context, StateSetter setState) => Scaffold(
+ body: DraggableScrollableSheet(
+ initialChildSize: 0.25,
+ snap: true,
+ snapSizes: const <double>[0.25, 0.5, 1.0],
+ controller: controller,
+ builder: (BuildContext context, ScrollController scrollController) {
+ return ListView(
+ controller: scrollController,
+ children: <Widget>[
+ ElevatedButton(
+ onPressed: () => setState(() {
+ controller = controller2;
+ }),
+ child: const Text('Switch controller'),
+ ),
+ Container(
+ height: 10000,
+ color: Colors.blue,
+ ),
+ ],
+ );
+ },
+ ),
+ ),
+ ),
+ ));
+ expect(controller1.isAttached, true);
+ expect(controller2.isAttached, false);
+
+ controller1.addListener(() {
+ loggedSizes.add(controller1.size);
+ });
+ controller1.jumpTo(0.5);
+ expect(loggedSizes, <double>[0.5].map((double v) => closeTo(v, precisionErrorTolerance)));
+ loggedSizes.clear();
+
+ await tester.tap(find.text('Switch controller'));
+ await tester.pump();
+
+ expect(controller1.isAttached, false);
+ expect(controller2.isAttached, true);
+
+ controller2.addListener(() {
+ loggedSizes.add(controller2.size);
+ });
+ controller2.jumpTo(1.0);
+ expect(loggedSizes, <double>[1.0].map((double v) => closeTo(v, precisionErrorTolerance)));
+ });
}