@@ -170,6 +170,10 @@ class ShowCaseWidget extends StatefulWidget {
170170 this .hideFloatingActionWidgetForShowcase = const [],
171171 });
172172
173+ static GlobalKey ? activeTargetWidget (BuildContext context) => context
174+ .findAncestorStateOfType <ShowCaseWidgetState >()
175+ ? .getCurrentActiveShowcaseKey;
176+
173177 static ShowCaseWidgetState of (BuildContext context) {
174178 final state = context.findAncestorStateOfType <ShowCaseWidgetState >();
175179 if (state != null ) {
@@ -270,7 +274,7 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
270274 super .initState ();
271275 globalTooltipActions = widget.globalTooltipActions;
272276 globalTooltipActionConfig = widget.globalTooltipActionConfig;
273- initRootWidget ();
277+ _initRootWidget ();
274278 }
275279
276280 @override
@@ -369,7 +373,7 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
369373 next ();
370374 }
371375
372- void initRootWidget () {
376+ void _initRootWidget () {
373377 WidgetsBinding .instance.addPostFrameCallback ((_) {
374378 if (! mounted) return ;
375379 final rootWidget = context.findRootAncestorStateOfType <State <Overlay >>();
@@ -383,34 +387,50 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
383387 /// Starts Showcase view from the beginning of specified list of widget ids.
384388 /// If this function is used when showcase has been disabled then it will
385389 /// throw an exception.
386- void startShowCase (List <GlobalKey > widgetIds) {
390+ ///
391+ /// [delay] is optional and it will be used to delay the start of showcase
392+ /// which is useful when animation may take some time to complete.
393+ ///
394+ /// Refer this issue https://github.com/SimformSolutionsPvtLtd/flutter_showcaseview/issues/378
395+ void startShowCase (
396+ List <GlobalKey > widgetIds, {
397+ Duration delay = Duration .zero,
398+ }) {
387399 if (! enableShowcase) {
388400 throw Exception (
389401 "You are trying to start Showcase while it has been disabled with "
390402 "`enableShowcase` parameter to false from ShowCaseWidget" ,
391403 );
392404 }
393- if (! mounted) return ;
394- ids = widgetIds;
395- activeWidgetId = 0 ;
396- _onStart ();
397- updateOverlay? .call (isShowcaseRunning);
405+ Future .delayed (
406+ delay,
407+ () {
408+ if (! mounted) return ;
409+ ids = widgetIds;
410+ activeWidgetId = 0 ;
411+ _onStart ();
412+ updateOverlay? .call (isShowcaseRunning);
413+ },
414+ );
398415 }
399416
400417 /// Completes showcase of given key and starts next one
401418 /// otherwise will finish the entire showcase view
402- Future < void > completed (GlobalKey ? key) async {
419+ void completed (GlobalKey ? key) {
403420 if (ids != null && ids! [activeWidgetId! ] == key && mounted) {
404- await _onComplete ();
405- if (! mounted) return ;
406- activeWidgetId = activeWidgetId! + 1 ;
407- _onStart ();
421+ _onComplete ().then (
422+ (_) {
423+ if (! mounted) return ;
424+ activeWidgetId = activeWidgetId! + 1 ;
425+ _onStart ();
408426
409- if (activeWidgetId! >= ids! .length) {
410- _cleanupAfterSteps ();
411- widget.onFinish? .call ();
412- }
413- updateOverlay? .call (isShowcaseRunning);
427+ if (activeWidgetId! >= ids! .length) {
428+ _cleanupAfterSteps ();
429+ widget.onFinish? .call ();
430+ }
431+ updateOverlay? .call (isShowcaseRunning);
432+ },
433+ );
414434 }
415435 }
416436
@@ -446,18 +466,21 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
446466
447467 /// Completes current active showcase and starts previous one
448468 /// otherwise will finish the entire showcase view
449- Future < void > previous () async {
469+ void previous () {
450470 if (ids != null && ((activeWidgetId ?? 0 ) - 1 ) >= 0 && mounted) {
451- await _onComplete ();
452- if (! mounted) return ;
471+ _onComplete ().then (
472+ (_) {
473+ if (! mounted) return ;
453474
454- activeWidgetId = activeWidgetId! - 1 ;
455- _onStart ();
456- if (activeWidgetId! >= ids! .length) {
457- _cleanupAfterSteps ();
458- widget.onFinish? .call ();
459- }
460- updateOverlay? .call (isShowcaseRunning);
475+ activeWidgetId = activeWidgetId! - 1 ;
476+ _onStart ();
477+ if (activeWidgetId! >= ids! .length) {
478+ _cleanupAfterSteps ();
479+ widget.onFinish? .call ();
480+ }
481+ updateOverlay? .call (isShowcaseRunning);
482+ },
483+ );
461484 }
462485 }
463486
@@ -502,24 +525,18 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
502525 }
503526
504527 Future <void > _onComplete () async {
505- final futures = < Future > [];
506528 final currentControllers = _getCurrentActiveControllers;
507529 final controllerLength = currentControllers.length;
508530
509- for (var i = 0 ; i < controllerLength; i++ ) {
510- final controller = currentControllers[i];
511- if ((controller.config.disableScaleAnimation ??
512- widget.disableScaleAnimation) ||
513- controller.reverseAnimationCallback == null ) {
514- continue ;
515- }
516- futures.add (controller.reverseAnimationCallback! .call ());
517- }
518- await Future .wait (futures);
531+ await Future .wait ([
532+ for (var i = 0 ; i < controllerLength; i++ )
533+ if (! (currentControllers[i].config.disableScaleAnimation ??
534+ widget.disableScaleAnimation) &&
535+ currentControllers[i].reverseAnimationCallback != null )
536+ currentControllers[i].reverseAnimationCallback! .call (),
537+ ]);
519538 widget.onComplete? .call (activeWidgetId, ids! [activeWidgetId! ]);
520- if (widget.autoPlay) {
521- _cancelTimer ();
522- }
539+ if (widget.autoPlay) _cancelTimer ();
523540 }
524541
525542 void _cancelTimer () {
@@ -550,6 +567,13 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
550567 required ShowcaseController controller,
551568 required int showcaseId,
552569 }) {
570+ assert (
571+ () {
572+ final stackTrace = StackTrace .current.toString ();
573+ return stackTrace.contains ('_ShowcaseState' );
574+ }(),
575+ 'This method should only be called from Showcase class' ,
576+ );
553577 _showcaseControllers
554578 .putIfAbsent (
555579 key,
@@ -566,16 +590,31 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
566590 required GlobalKey key,
567591 required int uniqueShowcaseKey,
568592 }) {
593+ assert (
594+ () {
595+ final stackTrace = StackTrace .current.toString ();
596+ return stackTrace.contains ('_ShowcaseState' );
597+ }(),
598+ 'This method should only be called from Showcase class' ,
599+ );
569600 _showcaseControllers[key]? .remove (uniqueShowcaseKey);
570601 }
571602
572- ShowcaseController getControllerForShowcase (
573- GlobalKey key,
574- int showcaseId,
575- ) {
603+ ShowcaseController getControllerForShowcase ({
604+ required GlobalKey key,
605+ required int showcaseId,
606+ }) {
607+ assert (
608+ () {
609+ final stackTrace = StackTrace .current.toString ();
610+ return stackTrace.contains ('_ShowcaseState' );
611+ }(),
612+ 'This method should only be called from Showcase class' ,
613+ );
576614 assert (
577615 _showcaseControllers[key]? [showcaseId] != null ,
578- 'Please register showcase controller first' ,
616+ 'Please register showcase controller first by calling '
617+ 'registerShowcaseController' ,
579618 );
580619 return _showcaseControllers[key]! [showcaseId]! ;
581620 }
0 commit comments