Skip to content

Commit a5dcbfb

Browse files
fix: 🐛 Add ShowcaseView.isTargetRendered method to check if a target is currently rendered
1 parent 789b7d8 commit a5dcbfb

4 files changed

Lines changed: 61 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- Fixed [#650](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/650) - Fix null-check crash in ShowcaseService.getController during didUpdateWidget.
44
- Fixed [#633](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/633) - Improve showcase flow by consolidating finish logic and handling missing targets
5+
- Fixed [#633](https://github.com/SimformSolutionsPvtLtd/showcaseview/issues/633) - Added `ShowcaseView.isTargetRendered` to detect whether a showcase target is currently rendered, replacing the 4.x.x `key.currentContext` / `key.currentWidget` check.
56

67
## [5.0.2]
78

doc/documentation.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,33 @@ ShowcaseView.get().previous();
550550
ShowcaseView.get().dismiss();
551551
```
552552

553+
### Detecting Whether a Target Is Rendered
554+
555+
Since 5.x.x, the `GlobalKey` passed to a `Showcase` is used only as a registry
556+
identifier and is no longer attached to the widget element. As a result,
557+
`key.currentContext` / `key.currentWidget` can no longer be used to detect
558+
whether a target widget is currently built (this worked in 4.x.x).
559+
560+
Use `isTargetRendered` instead to check whether a showcase target exists before
561+
advancing — for example, to avoid stepping through targets that are not present
562+
in the widget tree:
563+
564+
```dart
565+
final showcaseView = ShowcaseView.get();
566+
567+
if (showcaseView.isTargetRendered(nextKey)) {
568+
showcaseView.next();
569+
} else {
570+
// The next target is not rendered yet — handle it (e.g. dismiss or wait).
571+
showcaseView.dismiss();
572+
}
573+
```
574+
575+
> Note: `isTargetRendered` reports whether the `Showcase` for the given key is
576+
> currently mounted in the widget tree, not whether it is visible on screen.
577+
> If you only want missing targets to be skipped automatically while the
578+
> showcase advances, use the `skipIfTargetNotPresent` parameter instead.
579+
553580
## Event Callbacks
554581

555582
Handle showcase events:

lib/src/showcase/showcase_service.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ class ShowcaseService {
128128
}) =>
129129
getScope(scope: scope).controllers;
130130

131+
/// Returns whether a [Showcase] registered with the given [key] is currently
132+
/// mounted in the widget tree for the given [scope].
133+
///
134+
/// A controller is registered in [Showcase]'s `initState` and removed in its
135+
/// `dispose`, so the presence of a controller for [key] reflects whether the
136+
/// target widget is currently built. This is useful to detect whether the
137+
/// next showcase target exists before advancing the showcase.
138+
///
139+
/// * [key] - The GlobalKey passed to the [Showcase] to check.
140+
/// * [scope] - Optional scope name (defaults to [currentScope]).
141+
bool isTargetRendered(GlobalKey key, {String? scope}) =>
142+
getControllers(scope: scope ?? currentScope)[key]?.isNotEmpty ?? false;
143+
131144
/// Returns the [ShowcaseView] from the specified scope.
132145
///
133146
/// * [scope] - Optional scope name (defaults to [currentScope])

lib/src/showcase/showcase_view.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,26 @@ class ShowcaseView {
255255
_findEnclosingShowcaseView(widgetIds)._startShowcase(delay, widgetIds);
256256
}
257257

258+
/// Returns whether the [Showcase] registered with the given [key] is
259+
/// currently rendered (mounted in the widget tree) within this scope.
260+
///
261+
/// Since version 5.x.x the [GlobalKey] passed to [Showcase] is used as a
262+
/// registry identifier and is no longer attached to the widget element, so
263+
/// `key.currentContext` / `key.currentWidget` can no longer be used to detect
264+
/// whether the target is built. Use this method instead, for example to check
265+
/// if the next showcase target exists before calling [next]:
266+
///
267+
/// ```dart
268+
/// final showcaseView = ShowcaseView.get();
269+
/// if (showcaseView.isTargetRendered(nextKey)) {
270+
/// showcaseView.next();
271+
/// }
272+
/// ```
273+
///
274+
/// * [key] - The GlobalKey passed to the [Showcase] to check.
275+
bool isTargetRendered(GlobalKey key) =>
276+
ShowcaseService.instance.isTargetRendered(key, scope: scope);
277+
258278
/// Moves to next showcase if possible.
259279
///
260280
/// Will finish entire showcase if no more widgets to show.

0 commit comments

Comments
 (0)