Skip to content

Commit 76c328a

Browse files
authored
Merge pull request #475 from Erengun/master
Add useCupertinoTabController hook for automatic disposal of CupertinoTabController
2 parents 9506ee7 + c221c82 commit 76c328a

File tree

4 files changed

+140
-2
lines changed

4 files changed

+140
-2
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,9 @@ A series of hooks with no particular theme.
360360
| [useDraggableScrollableController](https://api.flutter.dev/flutter/widgets/DraggableScrollableController-class.html) | Creates a `DraggableScrollableController`. |
361361
| [useCarouselController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useCarouselController.html) | Creates and disposes a **`CarouselController`**. |
362362
| [useTreeSliverController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useTreeSliverController.html) | Creates a `TreeSliverController`. |
363-
| [useOverlayPortalController](https://api.flutter.dev/flutter/widgets/OverlayPortalController-class.html) | Creates and manages an `OverlayPortalController` for controlling the visibility of overlay content. The controller will be automatically disposed when no longer needed. |
364-
| [useSnapshotController](https://api.flutter.dev/flutter/widgets/SnapshotController-class.html) | Creates and manages a `SnapshotController` |
363+
| [useOverlayPortalController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useOverlayPortalController.html) | Creates and manages an `OverlayPortalController` for controlling the visibility of overlay content. The controller will be automatically disposed when no longer needed. |
364+
| [useSnapshotController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useSnapshotController.html) | Creates and manages a `SnapshotController` |
365+
| [useCupertinoController](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useCupertinoController.html) | Creates and manages a `CupertinoController` |
365366

366367
## Contributions
367368

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
part of 'hooks.dart';
2+
3+
/// Creates a [CupertinoTabController] that will be disposed automatically.
4+
///
5+
/// See also:
6+
/// - [CupertinoTabController]
7+
CupertinoTabController useCupertinoTabController({
8+
int initialIndex = 0,
9+
List<Object?>? keys,
10+
}) {
11+
return use(
12+
_CupertinoTabControllerHook(
13+
initialIndex: initialIndex,
14+
keys: keys,
15+
),
16+
);
17+
}
18+
19+
class _CupertinoTabControllerHook extends Hook<CupertinoTabController> {
20+
const _CupertinoTabControllerHook({
21+
required this.initialIndex,
22+
super.keys,
23+
});
24+
25+
final int initialIndex;
26+
27+
@override
28+
HookState<CupertinoTabController, Hook<CupertinoTabController>>
29+
createState() => _CupertinoTabControllerHookState();
30+
}
31+
32+
class _CupertinoTabControllerHookState
33+
extends HookState<CupertinoTabController, _CupertinoTabControllerHook> {
34+
late final controller = CupertinoTabController(
35+
initialIndex: hook.initialIndex,
36+
);
37+
38+
@override
39+
CupertinoTabController build(BuildContext context) => controller;
40+
41+
@override
42+
void dispose() => controller.dispose();
43+
44+
@override
45+
String get debugLabel => 'useCupertinoTabController';
46+
}

packages/flutter_hooks/lib/src/hooks.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:async';
22

3+
import 'package:flutter/cupertino.dart' show CupertinoTabController;
34
import 'package:flutter/foundation.dart';
45
import 'package:flutter/material.dart'
56
show
@@ -21,6 +22,7 @@ import 'framework.dart';
2122
part 'animation.dart';
2223
part 'async.dart';
2324
part 'carousel_controller.dart';
25+
part 'cupertino_tab_controller.dart';
2426
part 'debounced.dart';
2527
part 'draggable_scrollable_controller.dart';
2628
part 'expansion_tile_controller.dart';
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:flutter/cupertino.dart';
2+
import 'package:flutter/foundation.dart';
3+
import 'package:flutter_hooks/src/framework.dart';
4+
import 'package:flutter_hooks/src/hooks.dart';
5+
6+
import 'mock.dart';
7+
8+
void main() {
9+
testWidgets('debugFillProperties', (tester) async {
10+
await tester.pumpWidget(
11+
HookBuilder(builder: (context) {
12+
useCupertinoTabController();
13+
return const SizedBox();
14+
}),
15+
);
16+
17+
await tester.pump();
18+
19+
final element = tester.element(find.byType(HookBuilder));
20+
21+
expect(
22+
element
23+
.toDiagnosticsNode(style: DiagnosticsTreeStyle.offstage)
24+
.toStringDeep(),
25+
equalsIgnoringHashCodes(
26+
'HookBuilder\n'
27+
" │ useCupertinoTabController: Instance of 'CupertinoTabController'\n"
28+
' └SizedBox(renderObject: RenderConstrainedBox#00000)\n',
29+
),
30+
);
31+
});
32+
33+
group('useCupertinoTabController', () {
34+
testWidgets('initial values matches with real constructor', (tester) async {
35+
late CupertinoTabController controller;
36+
late CupertinoTabController controller2;
37+
38+
await tester.pumpWidget(
39+
HookBuilder(builder: (context) {
40+
controller2 = CupertinoTabController();
41+
controller = useCupertinoTabController();
42+
return Container();
43+
}),
44+
);
45+
46+
expect(controller.index, controller2.index);
47+
});
48+
testWidgets("returns a CupertinoTabController that doesn't change",
49+
(tester) async {
50+
late CupertinoTabController controller;
51+
late CupertinoTabController controller2;
52+
53+
await tester.pumpWidget(
54+
HookBuilder(builder: (context) {
55+
controller = useCupertinoTabController(initialIndex: 1);
56+
return Container();
57+
}),
58+
);
59+
60+
expect(controller, isA<CupertinoTabController>());
61+
62+
await tester.pumpWidget(
63+
HookBuilder(builder: (context) {
64+
controller2 = useCupertinoTabController(initialIndex: 1);
65+
return Container();
66+
}),
67+
);
68+
69+
expect(identical(controller, controller2), isTrue);
70+
});
71+
72+
testWidgets('passes hook parameters to the CupertinoTabController',
73+
(tester) async {
74+
late CupertinoTabController controller;
75+
76+
await tester.pumpWidget(
77+
HookBuilder(
78+
builder: (context) {
79+
controller = useCupertinoTabController(initialIndex: 2);
80+
81+
return Container();
82+
},
83+
),
84+
);
85+
86+
expect(controller.index, 2);
87+
});
88+
});
89+
}

0 commit comments

Comments
 (0)