Skip to content

Commit 7c9feea

Browse files
authored
Expose onAttach and onDetach in ScrollController subclasses (flutter#135721)
Fixes flutter#135574 This exposes the onAttach and onDetach callbacks of ScrollController in all of its subclasses.
1 parent 0f947a0 commit 7c9feea

File tree

6 files changed

+111
-0
lines changed

6 files changed

+111
-0
lines changed

packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ class FixedExtentScrollController extends ScrollController {
217217
/// [initialItem] defaults to zero.
218218
FixedExtentScrollController({
219219
this.initialItem = 0,
220+
super.onAttach,
221+
super.onDetach,
220222
});
221223

222224
/// The page to show when first creating the scroll view.

packages/flutter/lib/src/widgets/page_view.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ class PageController extends ScrollController {
116116
this.initialPage = 0,
117117
this.keepPage = true,
118118
this.viewportFraction = 1.0,
119+
super.onAttach,
120+
super.onDetach,
119121
}) : assert(viewportFraction > 0.0);
120122

121123
/// The page to show when first creating the [PageView].

packages/flutter/lib/src/widgets/scroll_controller.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ class TrackingScrollController extends ScrollController {
380380
super.initialScrollOffset,
381381
super.keepScrollOffset,
382382
super.debugLabel,
383+
super.onAttach,
384+
super.onDetach,
383385
});
384386

385387
final Map<ScrollPosition, VoidCallback> _positionToListener = <ScrollPosition, VoidCallback>{};

packages/flutter/test/widgets/list_wheel_scroll_view_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,37 @@ void main() {
8383
expect(tester.getSize(find.byType(ListWheelScrollView)), const Size(800.0, 600.0));
8484
});
8585

86+
testWidgetsWithLeakTracking('FixedExtentScrollController onAttach, onDetach', (WidgetTester tester) async {
87+
int attach = 0;
88+
int detach = 0;
89+
final FixedExtentScrollController controller = FixedExtentScrollController(
90+
onAttach: (_) { attach++; },
91+
onDetach: (_) { detach++; },
92+
);
93+
addTearDown(controller.dispose);
94+
95+
await tester.pumpWidget(
96+
Directionality(
97+
textDirection: TextDirection.ltr,
98+
child: ListWheelScrollView(
99+
controller: controller,
100+
itemExtent: 50.0,
101+
children: const <Widget>[],
102+
),
103+
),
104+
);
105+
await tester.pumpAndSettle();
106+
107+
expect(attach, 1);
108+
expect(detach, 0);
109+
110+
await tester.pumpWidget(Container());
111+
await tester.pumpAndSettle();
112+
113+
expect(attach, 1);
114+
expect(detach, 1);
115+
});
116+
86117
testWidgets('ListWheelScrollView needs positive magnification', (WidgetTester tester) async {
87118
expect(
88119
() {

packages/flutter/test/widgets/page_view_test.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,4 +1265,39 @@ void main() {
12651265
// Check the stretch factor in the first element of the transform matrix.
12661266
expect(transform.transform.storage.first, 1.0);
12671267
});
1268+
1269+
testWidgetsWithLeakTracking('PageController onAttach, onDetach', (WidgetTester tester) async {
1270+
int attach = 0;
1271+
int detach = 0;
1272+
final PageController controller = PageController(
1273+
onAttach: (_) { attach++; },
1274+
onDetach: (_) { detach++; },
1275+
);
1276+
addTearDown(controller.dispose);
1277+
1278+
await tester.pumpWidget(MaterialApp(
1279+
theme: ThemeData(useMaterial3: true),
1280+
home: Center(
1281+
child: PageView(
1282+
controller: controller,
1283+
physics: const PageScrollPhysics().applyTo(const ClampingScrollPhysics()),
1284+
children: const <Widget>[
1285+
Center(child: Text('First Page')),
1286+
Center(child: Text('Second Page')),
1287+
Center(child: Text('Third Page')),
1288+
],
1289+
),
1290+
),
1291+
));
1292+
await tester.pumpAndSettle();
1293+
1294+
expect(attach, 1);
1295+
expect(detach, 0);
1296+
1297+
await tester.pumpWidget(Container());
1298+
await tester.pumpAndSettle();
1299+
1300+
expect(attach, 1);
1301+
expect(detach, 1);
1302+
});
12681303
}

packages/flutter/test/widgets/tracking_scroll_controller_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,43 @@ void main() {
6060

6161
expect(controller.initialScrollOffset, 0.0);
6262
});
63+
64+
testWidgetsWithLeakTracking('TrackingScrollController saves offset', (WidgetTester tester) async {
65+
int attach = 0;
66+
int detach = 0;
67+
final TrackingScrollController controller = TrackingScrollController(
68+
onAttach: (_) { attach++; },
69+
onDetach: (_) { detach++; },
70+
);
71+
addTearDown(controller.dispose);
72+
const double listItemHeight = 100.0;
73+
74+
await tester.pumpWidget(Directionality(
75+
textDirection: TextDirection.ltr,
76+
child: PageView.builder(
77+
itemBuilder: (BuildContext context, int index) {
78+
return ListView(
79+
controller: controller,
80+
children: List<Widget>.generate(
81+
10,
82+
(int i) => SizedBox(
83+
height: listItemHeight,
84+
child: Text('Page$index-Item$i'),
85+
),
86+
).toList(),
87+
);
88+
},
89+
),
90+
));
91+
await tester.pumpAndSettle();
92+
93+
expect(attach, 1);
94+
expect(detach, 0);
95+
96+
await tester.pumpWidget(Container());
97+
await tester.pumpAndSettle();
98+
99+
expect(attach, 1);
100+
expect(detach, 1);
101+
});
63102
}

0 commit comments

Comments
 (0)