Skip to content

Commit 2cf17b3

Browse files
authored
feat: ✨ Expose onFinish and onDismiss listeners (#561)
1 parent eb339d2 commit 2cf17b3

File tree

3 files changed

+89
-12
lines changed

3 files changed

+89
-12
lines changed

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,17 @@ subtitle: Text('Try swiping this item'
344344

345345
## Functions of `ShowCaseView.get()` and `ShowCaseView.getNamed(scopeName)`:
346346

347-
| Function Name | Description |
348-
|---------------|-----------------------------------------------------|
349-
| startShowCase | Starting the showcase |
350-
| next | Starts next showcase |
351-
| previous | Starts previous showcase |
352-
| dismiss | Dismisses all showcases |
353-
| unRegister | UnRegister all showcases and the showcaseView scope |
347+
| Function Name | Description |
348+
|-------------------------|-----------------------------------------------------|
349+
| startShowCase | Starting the showcase |
350+
| next | Starts next showcase |
351+
| previous | Starts previous showcase |
352+
| dismiss | Dismisses all showcases |
353+
| addOnFinishCallback | Listener when showcase is finished |
354+
| removeOnFinishCallback | Clears OnFinishCallback |
355+
| addOnDismissCallback | Listener when showcase is dismissed |
356+
| removeOnDismissCallback | Clears OnDismissCallback |
357+
| unRegister | UnRegister all showcases and the showcaseView scope |
354358

355359
## Main Contributors
356360

example/lib/detailscreen.dart

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,29 @@ class _DetailState extends State<Detail> {
2020
// ShowcaseView then you can register new ShowcaseView
2121
ShowcaseView.register(scope: scopeName);
2222
WidgetsBinding.instance.addPostFrameCallback(
23-
(_) => ShowcaseView.getNamed(scopeName).startShowCase(
24-
[_one],
25-
delay: const Duration(milliseconds: 200),
26-
),
23+
(_) => ShowcaseView.getNamed(scopeName)
24+
..startShowCase([_one], delay: const Duration(milliseconds: 200))
25+
..addOnFinishCallback(_onShowcaseFinished)
26+
..addOnDismissCallback(_onShowcaseDismissed),
2727
);
2828
}
2929

30+
@override
31+
void dispose() {
32+
ShowcaseView.getNamed(scopeName)
33+
..removeOnFinishCallback(_onShowcaseFinished)
34+
..removeOnDismissCallback(_onShowcaseDismissed);
35+
super.dispose();
36+
}
37+
38+
void _onShowcaseFinished() {
39+
debugPrint("Showcase tour finished!");
40+
}
41+
42+
void _onShowcaseDismissed(GlobalKey? dismissedAt) {
43+
debugPrint("Showcase dismissed $dismissedAt");
44+
}
45+
3046
@override
3147
Widget build(BuildContext context) {
3248
return Scaffold(
@@ -51,6 +67,26 @@ class _DetailState extends State<Detail> {
5167
key: _one,
5268
title: 'Title',
5369
description: 'Desc',
70+
floatingActionWidget: FloatingActionWidget(
71+
left: 16,
72+
bottom: 16,
73+
child: Padding(
74+
padding: const EdgeInsets.all(16.0),
75+
child: ElevatedButton(
76+
style: ElevatedButton.styleFrom(
77+
backgroundColor: const Color(0xffEE5366),
78+
),
79+
onPressed: ShowcaseView.getNamed(scopeName).dismiss,
80+
child: const Text(
81+
'Close Showcase',
82+
style: TextStyle(
83+
color: Colors.white,
84+
fontSize: 15,
85+
),
86+
),
87+
),
88+
),
89+
),
5490
child: InkWell(
5591
onTap: () {},
5692
child: const Text(

lib/src/showcase/showcase_view.dart

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ class ShowcaseView {
173173
/// Map to store keys for which floating action widget should be hidden.
174174
late final Map<GlobalKey, bool> _hideFloatingWidgetKeys;
175175

176+
/// Stores functions to call when a onFinish event occurs.
177+
final List<VoidCallback> _onFinishCallbacks = [];
178+
179+
/// Stores functions to call when a onDismiss event occurs.
180+
final List<OnDismissCallback> _onDismissCallbacks = [];
181+
176182
/// Returns whether showcase is completed or not.
177183
bool get isShowCaseCompleted => _ids == null && _activeWidgetId == null;
178184

@@ -258,8 +264,13 @@ class ShowcaseView {
258264
void dismiss() {
259265
final idDoesNotExist =
260266
_activeWidgetId == null || (_ids?.length ?? -1) <= _activeWidgetId!;
267+
final dismissedAtKey = idDoesNotExist ? null : _ids?[_activeWidgetId!];
268+
269+
onDismiss?.call(dismissedAtKey);
270+
for (final callback in _onDismissCallbacks) {
271+
callback.call(dismissedAtKey);
272+
}
261273

262-
onDismiss?.call(idDoesNotExist ? null : _ids?[_activeWidgetId!]);
263274
if (!_mounted) return;
264275

265276
_cleanupAfterSteps();
@@ -273,6 +284,9 @@ class ShowcaseView {
273284
ShowcaseService.instance.unregister(scope: scope);
274285
_mounted = false;
275286
_cancelTimer();
287+
288+
_onFinishCallbacks.clear();
289+
_onDismissCallbacks.clear();
276290
}
277291

278292
/// Updates the overlay to reflect current showcase state.
@@ -301,6 +315,26 @@ class ShowcaseView {
301315
: globalFloatingActionWidget;
302316
}
303317

318+
/// Adds a listener that will be called when the showcase tour is finished.
319+
void addOnFinishCallback(VoidCallback listener) {
320+
_onFinishCallbacks.add(listener);
321+
}
322+
323+
/// Removes a listener that was previously added via [addOnFinishCallback].
324+
void removeOnFinishCallback(VoidCallback listener) {
325+
_onFinishCallbacks.remove(listener);
326+
}
327+
328+
/// Adds a listener that will be called when the showcase tour is dismissed.
329+
void addOnDismissCallback(OnDismissCallback listener) {
330+
_onDismissCallbacks.add(listener);
331+
}
332+
333+
/// Removes a listener that was previously added via [addOnDismissCallback].
334+
void removeOnDismissCallback(OnDismissCallback listener) {
335+
_onDismissCallbacks.remove(listener);
336+
}
337+
304338
void _startShowcase(
305339
Duration delay,
306340
List<GlobalKey<State<StatefulWidget>>> widgetIds,
@@ -345,6 +379,9 @@ class ShowcaseView {
345379
if (_activeWidgetId! >= _ids!.length) {
346380
_cleanupAfterSteps();
347381
onFinish?.call();
382+
for (final callback in _onFinishCallbacks) {
383+
callback.call();
384+
}
348385
} else {
349386
// Add a short delay before starting the next showcase to ensure proper state update
350387
// Then start the new showcase

0 commit comments

Comments
 (0)