### Installation Bundle Setup Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/linux/CMakeLists.txt Configures the installation prefix to create a relocatable bundle in the build directory. Ensures a clean build bundle directory on each installation. ```cmake # === Installation === # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() # Start with a clean build bundle directory every time. install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") ``` -------------------------------- ### Basic Showcase Implementation Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Demonstrates the basic setup for ShowcaseView, including registering the view, defining global keys for widgets, adding showcases to widgets, and starting the showcase sequence. ```dart // Import the package import 'package:showcaseview/showcaseview.dart'; // Register the showcase view ShowcaseView.register(); // Define global keys for your showcases GlobalKey _one = GlobalKey(); // Add showcases to widgets Showcase( key: _one, title: 'Menu', description: 'Click here to see menu options', child: Icon(Icons.menu), ), // Start the showcase void startShowcase() { ShowcaseView.get().startShowCase([_one]); } // Dispose the showcase view ShowcaseView.get().unregister(); ``` -------------------------------- ### Complete Showcase Implementation Example Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md A full example demonstrating registration, widget wrapping, and lifecycle management for a showcase sequence. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'ShowCase Example', theme: ThemeData(primarySwatch: Colors.blue), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage(); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { final GlobalKey _one = GlobalKey(); final GlobalKey _two = GlobalKey(); @override void initState() { super.initState(); // Register the showcase view ShowcaseView.register(); // Start showcase after the screen is rendered to ensure internal initialization. WidgetsBinding.instance.addPostFrameCallback( (_) => ShowcaseView.get().startShowCase([_one, _two]), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('ShowCase Example'), leading: Showcase( key: _one, title: 'Menu', description: 'Click here to see menu options', child: Icon(Icons.menu), ), ), floatingActionButton: Showcase( key: _two, title: 'Add', description: 'Click here to add new items', child: FloatingActionButton( onPressed: () {}, child: Icon(Icons.add), ), ), body: Center( child: Text('ShowCase Example'), ), ); } @override void dispose() { // Unregister the showcase view ShowcaseView.register(); ShowcaseView.get().unregister(); super.dispose(); } } ``` -------------------------------- ### Control Showcase Progression with Methods Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt This example shows how to use ShowcaseView's control methods to manage the showcase sequence. It includes starting, navigating, dismissing, and checking the status of showcases. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; class ShowcaseControlExample extends StatefulWidget { @override _ShowcaseControlExampleState createState() => _ShowcaseControlExampleState(); } class _ShowcaseControlExampleState extends State { final GlobalKey _key1 = GlobalKey(); final GlobalKey _key2 = GlobalKey(); final GlobalKey _key3 = GlobalKey(); @override void initState() { super.initState(); ShowcaseView.register(); } @override void dispose() { ShowcaseView.get().unregister(); super.dispose(); } void _demonstrateControls() { // Start showcase with specific widgets ShowcaseView.get().startShowCase( [_key1, _key2, _key3], delay: const Duration(milliseconds: 500), // Optional delay before starting ); } void _navigateNext() { // Move to next showcase ShowcaseView.get().next(); // Force next even when autoPlayLock is enabled ShowcaseView.get().next(force: true); } void _navigatePrevious() { // Move to previous showcase ShowcaseView.get().previous(); } void _dismissShowcase() { // Dismiss and trigger onDismiss callback ShowcaseView.get().dismiss(); } void _completeCurrentShowcase() { // Complete specific showcase and move to next final currentKey = ShowcaseView.get().getActiveShowcaseKey; if (currentKey != null) { ShowcaseView.get().completed(currentKey); } } void _checkStatus() { final showcaseView = ShowcaseView.get(); // Check if showcase is currently running final isRunning = showcaseView.isShowcaseRunning; print('Is showcase running: $isRunning'); // Check if showcase is completed final isCompleted = showcaseView.isShowCaseCompleted; print('Is showcase completed: $isCompleted'); // Get current active showcase key final activeKey = showcaseView.getActiveShowcaseKey; print('Active showcase key: $activeKey'); } void _updateOverlay() { // Manually update the showcase overlay ShowcaseView.get().updateOverlay(); } void _hideFloatingWidgetForSpecificShowcases() { // Dynamically update which showcases should hide the floating action widget ShowcaseView.get().hideFloatingActionWidgetForKeys([_key1, _key3]); // Get list of hidden floating action keys final hiddenKeys = ShowcaseView.get().hiddenFloatingActionKeys; print('Hidden floating action keys: $hiddenKeys'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Showcase Controls')), body: Column( children: [ Showcase( key: _key1, title: 'Step 1', description: 'First showcase item', child: const Icon(Icons.looks_one, size: 48), ), Showcase( key: _key2, title: 'Step 2', description: 'Second showcase item', child: const Icon(Icons.looks_two, size: 48), ), Showcase( key: _key3, title: 'Step 3', description: 'Third showcase item', child: const Icon(Icons.looks_3, size: 48), ), const SizedBox(height: 20), Wrap( spacing: 8, runSpacing: 8, children: [ ElevatedButton( onPressed: _demonstrateControls, child: const Text('Start'), ), ElevatedButton( onPressed: _navigatePrevious, child: const Text('Previous'), ), ElevatedButton( onPressed: _navigateNext, child: const Text('Next'), ), ElevatedButton( onPressed: _dismissShowcase, child: const Text('Dismiss'), ), ElevatedButton( onPressed: _checkStatus, child: const Text('Check Status'), ), ], ), ], ), ); } } ``` -------------------------------- ### Configure Installation Paths Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Sets up installation directories for the application bundle, ensuring support files are placed next to the executable for in-place execution. ```cmake # === Installation === # Support files are copied into place next to the executable, so that it can # run in place. This is done instead of making a separate bundle (as on Linux) # so that building and running from within Visual Studio will work. set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") ``` -------------------------------- ### Install Application and Runtime Components Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Installs the main executable, ICU data, Flutter library, and any bundled plugin libraries to their respective runtime destinations. ```cmake install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Install Flutter Assets Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Recursively removes and then copies the Flutter assets directory to the installation data directory to ensure the latest assets are included. ```cmake # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Start Default Scope Showcase - Main Screen Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Starts the showcase sequence for the default scope using a list of GlobalKeys. This should be called after the frame has been rendered. ```dart ShowcaseView.get().startShowCase([_homeKey, _searchKey]); ``` -------------------------------- ### CMake Project Setup Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/linux/CMakeLists.txt Basic CMake project configuration including minimum version, project name, and binary/application IDs. Sets up CMAKE_INSTALL_RPATH for library linking. ```cmake cmake_minimum_required(VERSION 3.10) project(runner LANGUAGES CXX) set(BINARY_NAME "example") set(APPLICATION_ID "com.simform.example") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") ``` -------------------------------- ### Install AOT Library Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compilation library for Profile and Release builds. ```cmake # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Start Scoped Showcase Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Initiate a showcase tour using a specific registered scope. ```dart ShowcaseView.get(scope: 'profile').startShowCase([_one, _two, _three]); ``` -------------------------------- ### Custom Tooltip Widget Example Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Use Showcase.withWidget to display a custom widget as a tooltip. This example includes a custom container with user profile information, action buttons, and styling for the target widget. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; class CustomTooltipExample extends StatelessWidget { final GlobalKey _avatarKey = GlobalKey(); @override Widget build(BuildContext context) { return Showcase.withWidget( key: _avatarKey, // Custom tooltip widget container: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ CircleAvatar( backgroundColor: Colors.blue, child: const Icon(Icons.person, color: Colors.white), ), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: const [ Text( 'User Profile', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), Text( 'View your account details', style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ], ), const SizedBox(height: 12), const Text( 'Tap here to access your profile settings, update your avatar, ' 'and manage your account preferences.', style: TextStyle(fontSize: 14), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => ShowcaseView.get().previous(), child: const Text('Back'), ), const SizedBox(width: 8), ElevatedButton( onPressed: () => ShowcaseView.get().next(), child: const Text('Got it!'), ), ], ), ], ), ), // Target styling targetShapeBorder: const CircleBorder(), targetBorderRadius: const BorderRadius.all(Radius.circular(50)), targetPadding: const EdgeInsets.all(4), // Overlay settings overlayColor: Colors.black87, overlayOpacity: 0.8, blurValue: 3.0, // Tooltip positioning tooltipPosition: TooltipPosition.bottom, toolTipMargin: 20, targetTooltipGap: 12, toolTipSlideEndDistance: 10, // Animation movingAnimationDuration: const Duration(milliseconds: 1500), disableMovingAnimation: false, // Auto-scroll enableAutoScroll: true, scrollAlignment: 0.5, // Interaction onTargetClick: () => print('Avatar tapped'), disposeOnTap: false, onBarrierClick: () => print('Outside tapped'), disableBarrierInteraction: false, disableDefaultTargetGestures: false, // Action buttons for custom tooltip tooltipActionConfig: const TooltipActionConfig( position: TooltipActionPosition.outside, alignment: MainAxisAlignment.center, gapBetweenContentAndAction: 8, ), tooltipActions: [ TooltipActionButton.custom( button: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(20), ), child: const Text( 'Next Step', style: TextStyle(color: Colors.white), ), ), ), ], // The widget to showcase child: const CircleAvatar( radius: 24, backgroundColor: Colors.blue, child: Icon(Icons.person, color: Colors.white), ), ); } } ``` -------------------------------- ### Start Named Scope Showcase - Profile Screen Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Starts the showcase sequence for a named scope ('profile_tour') using a list of GlobalKeys. This method is used to initiate showcases for specific, named scopes. ```dart ShowcaseView.getNamed('profile_tour').startShowCase([ _avatarKey, _editKey, _settingsKey, ]); ``` -------------------------------- ### Trigger Showcase on Screen Load Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Use addPostFrameCallback in initState to ensure the UI is fully rendered before starting the showcase sequence. ```dart @override void initState() { super.initState(); // Delayed execution to ensure the UI is fully rendered WidgetsBinding.instance.addPostFrameCallback( (_) => ShowcaseView.get().startShowCase([_one, _two, _three]), ); } ``` -------------------------------- ### Install Assets and AOT Library Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/linux/CMakeLists.txt Installs the Flutter assets directory and the AOT (Ahead-Of-Time compilation) library for non-Debug builds. Ensures assets are re-copied on each build. ```cmake # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Import ShowcaseView Package Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Import the ShowcaseView package into your Dart files to start using its features. ```dart import 'package:showcaseview/showcaseview.dart'; ``` -------------------------------- ### Dart Deprecation Example Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/CONTRIBUTING.md Demonstrates how to mark a method or field as deprecated in Dart. Use this to inform users about upcoming removals and suggest alternative methods. ```dart @Deprecated('Will be removed in v1.5.0, use nonDeprecatedFeature() instead') void deprecatedFeature() {} ``` -------------------------------- ### Implement ShowcaseView (Pre-5.0.0 vs 5.0.0+) Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Shows the transition from context-based ShowCaseWidget control to the global ShowcaseView registration pattern. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: ShowCaseWidget( // Prior to 5.x.x, you wrapped your page with ShowCaseWidget builder: (context) => const MyPage(), ), ); } } class MyPage extends StatefulWidget { const MyPage({super.key}); @override State createState() => MyPageState(); } class MyPageState extends State { final _one = GlobalKey(); final _two = GlobalKey(); @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { // Context-based control ShowCaseWidget.of(context).startShowCase([_one, _two]); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Legacy ShowCase Usage')), body: Center( child: Showcase( key: _one, title: 'Legacy', description: 'Context-based control via ShowCaseWidget.of(context)', child: const Icon(Icons.info), ), ), floatingActionButton: FloatingActionButton( onPressed: onClose, child: const Icon(Icons.close), ), ); } void onClose() { ShowCaseWidget.of(context).dismiss(); } } ``` ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: const MyPage(), ); } } class MyPage extends StatefulWidget { const MyPage({super.key}); @override State createState() => MyPageState(); } class MyPageState extends State { final _one = GlobalKey(); final _two = GlobalKey(); @override void initState() { super.initState(); // Register once and (optionally) provide global configs ShowcaseView.register( autoPlayDelay: const Duration(seconds: 3), onStart: (index, key) => debugPrint('Started $index'), onComplete: (index, key) => debugPrint('Completed $index'), ); // Start after the first frame to ensure layout is ready WidgetsBinding.instance.addPostFrameCallback((_) { ShowcaseView.get().startShowCase([_one, _two]); }); } @override void dispose() { // Always unregister to clean up ShowcaseView.get().unregister(); super.dispose(); } void onClose() { ShowcaseView.get().dismiss(); } } ``` -------------------------------- ### Showcase Widget Configuration Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Demonstrates the comprehensive configuration of the Showcase widget, including tooltip content, styling, appearance, animation, interaction callbacks, auto-scroll, action buttons, and a floating action widget. Use this for standard tooltip presentations. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; class ShowcaseExample extends StatelessWidget { final GlobalKey _settingsKey = GlobalKey(); @override Widget build(BuildContext context) { return Showcase( key: _settingsKey, // Tooltip content title: 'Settings', description: 'Configure your app preferences here', // Text styling titleTextStyle: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), descTextStyle: const TextStyle( color: Colors.white70, fontSize: 14, ), titleTextAlign: TextAlign.center, descriptionTextAlign: TextAlign.start, titleAlignment: Alignment.center, descriptionAlignment: Alignment.centerLeft, titlePadding: const EdgeInsets.only(bottom: 8), descriptionPadding: EdgeInsets.zero, // Tooltip appearance tooltipBackgroundColor: Colors.blue, textColor: Colors.white, tooltipPadding: const EdgeInsets.all(12), tooltipBorderRadius: BorderRadius.circular(12), toolTipMargin: 14, showArrow: true, tooltipPosition: TooltipPosition.bottom, // top, bottom, left, right targetTooltipGap: 10, // Target widget styling targetPadding: const EdgeInsets.all(8), targetBorderRadius: BorderRadius.circular(8), targetShapeBorder: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8)), ), // Overlay appearance overlayColor: Colors.black, overlayOpacity: 0.75, blurValue: 2.0, // Animation settings movingAnimationDuration: const Duration(milliseconds: 2000), disableMovingAnimation: false, disableScaleAnimation: false, scaleAnimationDuration: const Duration(milliseconds: 300), scaleAnimationCurve: Curves.easeIn, toolTipSlideEndDistance: 7, // Interaction callbacks onTargetClick: () => print('Target clicked'), disposeOnTap: true, // Required with onTargetClick onTargetLongPress: () => print('Target long pressed'), onTargetDoubleTap: () => print('Target double tapped'), onToolTipClick: () => print('Tooltip clicked'), onBarrierClick: () => print('Barrier clicked'), disableBarrierInteraction: false, disableDefaultTargetGestures: false, // Auto-scroll settings enableAutoScroll: true, scrollAlignment: 0.5, scrollLoadingWidget: const CircularProgressIndicator(), // Auto-play delay override autoPlayDelay: const Duration(seconds: 5), // Tooltip action buttons tooltipActionConfig: const TooltipActionConfig( position: TooltipActionPosition.inside, alignment: MainAxisAlignment.spaceBetween, actionGap: 10, gapBetweenContentAndAction: 12, ), tooltipActions: [ TooltipActionButton( type: TooltipDefaultActionType.previous, name: 'Back', backgroundColor: Colors.white24, textStyle: const TextStyle(color: Colors.white), borderRadius: BorderRadius.circular(20), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), TooltipActionButton( type: TooltipDefaultActionType.next, name: 'Continue', backgroundColor: Colors.white, textStyle: const TextStyle(color: Colors.blue), ), ], // Per-showcase floating action widget floatingActionWidget: FloatingActionWidget( right: 16, bottom: 16, child: TextButton( onPressed: () => ShowcaseView.get().dismiss(), child: const Text('Skip'), ), ), // The widget to showcase child: IconButton( icon: const Icon(Icons.settings), onPressed: () {}, ), ); } } ``` -------------------------------- ### Register ShowcaseView with Configurations Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Shows how to register ShowcaseView with various global configurations, including autoplay delay, accessibility support, global floating action widgets, tooltip action configurations, and specific tooltip action button settings. ```dart ShowcaseView.register( autoPlayDelay: const Duration(seconds: 3), semanticEnable: true, // Enable accessibility support globally globalFloatingActionWidget: (showcaseContext) => FloatingActionWidget( left: 16, bottom: 16, child: Padding( padding: const EdgeInsets.all(16.0), child: ElevatedButton( onPressed: () => ShowcaseView.get().dismiss(), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xffEE5366), ), child: const Text( 'Skip', style: TextStyle( color: Colors.white, fontSize: 15, ), ), ), ), ), ), globalTooltipActionConfig: const TooltipActionConfig( position: TooltipActionPosition.inside, alignment: MainAxisAlignment.spaceBetween, actionGap: 20, ), globalTooltipActions: [ TooltipActionButton( type: TooltipDefaultActionType.previous, textStyle: const TextStyle( color: Colors.white, ), // Here we don't need previous action for the first showcase widget // so we hide this action for the first showcase widget hideActionWidgetForShowcase: [_firstShowcaseWidget], ), TooltipActionButton( type: TooltipDefaultActionType.next, textStyle: const TextStyle( color: Colors.white, ), // Here we don't need next action for the last showcase widget so we // hide this action for the last showcase widget hideActionWidgetForShowcase: [_lastShowcaseWidget], ), ], ); ``` -------------------------------- ### Register Showcase Configurations Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Set global or scope-specific configurations for showcases. ```dart ShowcaseView.register( // appropriate configurations ) ``` ```dart ShowcaseView.register( scope: 'profile', // other configurations ) ``` -------------------------------- ### Add OnStart Callback Dynamically Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Dynamically add or remove `onStart` callbacks at runtime using `ShowcaseView.get().addOnstartCallback()` and `ShowcaseView.get().removeOnstartCallback()`. This is useful for callbacks from deeply nested widgets. ```dart // Add a callback for when each showcase step completes ShowcaseView.get().addOnstartCallback((index, key) { print('Showcase step $index started with key: $key'); // Perform custom actions here }); // Remove a previously added callback ShowcaseView.get().removeOnstartCallback(callbackFunction); ``` ```dart ShowcaseView.getNamed('profile').addOnstartCallback((index, key) { print('Profile showcase started at step $index'); }); ``` -------------------------------- ### Configure Build Options Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Sets up build configurations (Debug, Profile, Release) based on whether the generator is multi-config. Ensures a default build type is set if none is specified. ```cmake get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE) else() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() endif() ``` -------------------------------- ### Initialize and Configure ShowcaseView Manager Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Register the ShowcaseView manager with global settings, event callbacks, and floating action widgets. Ensure unregister is called in the dispose method to prevent memory leaks. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { final GlobalKey _menuKey = GlobalKey(); final GlobalKey _profileKey = GlobalKey(); final GlobalKey _addKey = GlobalKey(); @override void initState() { super.initState(); // Register ShowcaseView with comprehensive configuration ShowcaseView.register( // Auto-play configuration autoPlay: false, autoPlayDelay: const Duration(seconds: 3), enableAutoPlayLock: false, // Animation settings disableMovingAnimation: false, disableScaleAnimation: false, blurValue: 1.0, // Auto-scroll for off-screen widgets enableAutoScroll: true, scrollDuration: const Duration(milliseconds: 500), // Barrier interaction disableBarrierInteraction: false, // Enable/disable showcase globally enableShowcase: true, // Accessibility support semanticEnable: true, // Global floating action widget (e.g., Skip button) globalFloatingActionWidget: (context) => FloatingActionWidget( left: 16, bottom: 16, child: ElevatedButton( onPressed: () => ShowcaseView.get().dismiss(), child: const Text('Skip Tour'), ), ), hideFloatingActionWidgetForShowcase: [_addKey], // Hide for specific showcases // Global tooltip action buttons globalTooltipActionConfig: const TooltipActionConfig( position: TooltipActionPosition.inside, alignment: MainAxisAlignment.spaceBetween, actionGap: 20, ), globalTooltipActions: [ TooltipActionButton( type: TooltipDefaultActionType.previous, textStyle: const TextStyle(color: Colors.white), hideActionWidgetForShowcase: [_menuKey], // No previous on first item ), TooltipActionButton( type: TooltipDefaultActionType.next, textStyle: const TextStyle(color: Colors.white), hideActionWidgetForShowcase: [_addKey], // No next on last item ), ], // Event callbacks onStart: (index, key) => print('Started showcase $index'), onComplete: (index, key) => print('Completed showcase $index'), onFinish: () => print('All showcases completed'), onDismiss: (key) => print('Dismissed at $key'), ); // Start showcase after frame is rendered WidgetsBinding.instance.addPostFrameCallback((_) { ShowcaseView.get().startShowCase([_menuKey, _profileKey, _addKey]); }); } @override void dispose() { ShowcaseView.get().unregister(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: Showcase( key: _menuKey, title: 'Menu', description: 'Access navigation options', child: const Icon(Icons.menu), ), ), body: const Center(child: Text('Content')), ); } } ``` -------------------------------- ### Navigate Next Step in ShowcaseView Tour Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Use `ShowcaseView.getNamed('tour_name').next()` to proceed to the next step in a named tour. Ensure the tour has been initialized. ```dart onPressed: () => ShowcaseView.getNamed('profile_tour').next(), ``` -------------------------------- ### Profile Build Configuration Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Copies release linker and compiler flags to the profile configuration to ensure consistent performance settings. ```cmake set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") ``` -------------------------------- ### Enable Unicode Support Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Adds preprocessor definitions to enable Unicode support for all projects. ```cmake add_definitions(-DUNICODE -D_UNICODE) ``` -------------------------------- ### Flutter and System Dependencies Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/linux/CMakeLists.txt Includes the Flutter managed directory and finds PkgConfig for GTK+ 3.0. Also defines the APPLICATION_ID for the build. ```cmake set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") # Flutter library and tool build rules. add_subdirectory(${FLUTTER_MANAGED_DIR}) # System-level dependencies. find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") ``` -------------------------------- ### Register Global Showcase Event Callbacks Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Handle showcase lifecycle events by registering callbacks using `ShowcaseView.register()`. Events include `onStart`, `onComplete`, `onFinish`, and `onDismiss`. ```dart ShowcaseView.register( onStart: (index, key) { print('Started showcase $index'); }, onComplete: (index, key) { print('Completed showcase $index'); }, onFinish: () { print('All showcases completed'); }, onDismiss: (reason) { print('Showcase dismissed because: $reason'); }, ) ``` -------------------------------- ### Create a Custom Tooltip Widget Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Utilize `Showcase.withWidget` to construct a completely custom tooltip. Specify dimensions, target shape, and the custom widget content. ```dart Showcase.withWidget( key: _customKey, height: 80, width: 140, targetShapeBorder: CircleBorder(), container: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Custom Tooltip', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), SizedBox(height: 5), Text('This is a completely custom tooltip widget', style: TextStyle(color: Colors.white)), ], ), child: Icon(Icons.star), ) ``` -------------------------------- ### Add ShowcaseView Dependency Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Add the ShowcaseView package to your pubspec.yaml file to include it in your project. ```yaml dependencies: showcaseview: ``` -------------------------------- ### Configure Flutter Linux Build Environment Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/linux/flutter/CMakeLists.txt Sets up the Flutter engine, system dependencies, and custom build targets for a Linux project. ```cmake cmake_minimum_required(VERSION 3.10) set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") # Configuration provided via flutter tool. include(${EPHEMERAL_DIR}/generated_config.cmake) # TODO: Move the rest of this into files in ephemeral. See # https://github.com/flutter/flutter/issues/57146. # Serves the same purpose as list(TRANSFORM ... PREPEND ...), # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") foreach(element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") endforeach(element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() # === Flutter Library === # System-level dependencies. find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") # Published to parent scope for install step. set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS "fl_basic_message_channel.h" "fl_binary_codec.h" "fl_binary_messenger.h" "fl_dart_project.h" "fl_engine.h" "fl_json_message_codec.h" "fl_json_method_codec.h" "fl_message_codec.h" "fl_method_call.h" "fl_method_channel.h" "fl_method_codec.h" "fl_method_response.h" "fl_plugin_registrar.h" "fl_plugin_registry.h" "fl_standard_message_codec.h" "fl_standard_method_codec.h" "fl_string_codec.h" "fl_value.h" "fl_view.h" "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) add_dependencies(flutter flutter_assemble) # === Flutter tool backend === # _phony_ is a non-existent file to force this command to run every time, # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/_phony_ COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" ${FLUTTER_LIBRARY_HEADERS} ) ``` -------------------------------- ### Configure Auto Play Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Enable automatic advancement through showcase items with a specified delay. ```dart ShowcaseView.register( autoPlay: true, autoPlayDelay: Duration(milliseconds: 3000), enableAutoPlayLock: true, ) ``` -------------------------------- ### Trigger Showcase on Button Press Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Initiate the showcase sequence by calling startShowCase on a user-triggered event like a button press. ```dart ElevatedButton( child: Text('Start Showcase'), onPressed: () { ShowcaseView.get().startShowCase([_one, _two, _three]); }, ) ``` -------------------------------- ### Manage OnFinish Callbacks Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Register or remove callbacks triggered when the entire showcase tour finishes. ```dart // Add a callback for when the showcase tour is finished ShowcaseView.get().addOnFinishCallback(() { print('Showcase tour finished'); // Perform custom actions here }); // Remove a previously added callback ShowcaseView.get().removeOnFinishCallback(callbackFunction); ``` ```dart ShowcaseView.getNamed('profile').addOnFinishCallback(() { print('Profile showcase tour finished'); }); ``` -------------------------------- ### Configure Flutter Tool Backend Custom Command in CMake Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/flutter/CMakeLists.txt Sets up a custom command to run the Flutter tool backend, generating necessary files for the build. A phony target is used to ensure the command executes on every build. ```cmake # === Flutter tool backend === # _phony_ is a non-existent file to force this command to run every time, # since currently there's no way to get a full input/output list from the # flutter tool. set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ${PHONY_OUTPUT} COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" windows-x64 $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ) ``` -------------------------------- ### Implement Custom Tooltip Button Widget Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Shows how to use TooltipActionButton.custom to inject a completely custom widget as a navigation button. ```dart class CustomButtonExample extends StatelessWidget { final GlobalKey _key = GlobalKey(); @override Widget build(BuildContext context) { return Showcase( key: _key, title: 'Custom Button', description: 'Using a completely custom button widget', tooltipActionConfig: const TooltipActionConfig( position: TooltipActionPosition.outside, alignment: MainAxisAlignment.center, gapBetweenContentAndAction: 12, ), tooltipActions: [ // Fully custom button widget TooltipActionButton.custom( button: GestureDetector( onTap: () => ShowcaseView.get().next(), child: Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Colors.purple, Colors.blue], ), borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.blue.withOpacity(0.4), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Text( 'Awesome! Next', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), SizedBox(width: 8), Icon(Icons.rocket_launch, color: Colors.white, size: 18), ], ), ), ), // Hide this button for specific showcases hideActionWidgetForShowcase: [], ), ], child: const Icon(Icons.star, size: 48, color: Colors.amber), ); } } ``` -------------------------------- ### Highlight Multiple Widgets Simultaneously Source: https://context7.com/simformsolutionspvtltd/showcaseview/llms.txt Use the same GlobalKey for multiple Showcase widgets to display them together in a single step. Common settings like barrier tap and colors are derived from the first initialized Showcase. ```dart import 'package:flutter/material.dart'; import 'package:showcaseview/showcaseview.dart'; class MultiShowcaseExample extends StatefulWidget { @override _MultiShowcaseExampleState createState() => _MultiShowcaseExampleState(); } class _MultiShowcaseExampleState extends State { // Same key for multiple showcases - they'll display together final GlobalKey _socialButtonsKey = GlobalKey(); final GlobalKey _singleKey = GlobalKey(); @override void initState() { super.initState(); ShowcaseView.register(); WidgetsBinding.instance.addPostFrameCallback((_) { // Both social button showcases will appear simultaneously ShowcaseView.get().startShowCase([_socialButtonsKey, _singleKey]); }); } @override void dispose() { ShowcaseView.get().unregister(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Multi-Showcase Demo')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Social Sharing', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), // Row of social buttons - all highlighted together Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // First social button with shared key Showcase( key: _socialButtonsKey, // Same key title: 'Share Options', description: 'Share content on social media', // Note: Properties from the first initialized Showcase are used // for common settings like barrier tap and colors child: IconButton( icon: const Icon(Icons.facebook, color: Colors.blue, size: 40), onPressed: () {}, ), ), const SizedBox(width: 16), // Second social button with same key Showcase( key: _socialButtonsKey, // Same key - highlights simultaneously title: 'Twitter', description: 'Share on Twitter', child: IconButton( icon: const Icon(Icons.share, color: Colors.lightBlue, size: 40), onPressed: () {}, ), ), const SizedBox(width: 16), // Third social button with same key Showcase( key: _socialButtonsKey, // Same key - highlights simultaneously title: 'Email', description: 'Share via email', child: IconButton( icon: const Icon(Icons.email, color: Colors.red, size: 40), onPressed: () {}, ), ), ], ), const SizedBox(height: 40), // Single showcase (separate key) Showcase( key: _singleKey, title: 'Download', description: 'Download the content', child: ElevatedButton.icon( onPressed: () {}, icon: const Icon(Icons.download), label: const Text('Download'), ), ), ], ), ), ); } } ``` -------------------------------- ### Programmatically Control Showcase Flow Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/doc/documentation.md Control the showcase progression using static methods on `ShowcaseView.get()`. Available methods include `next()`, `previous()`, and `dismiss()`. ```dart // Navigate to next showcase ShowcaseView.get().next(); // Navigate to previous showcase ShowcaseView.get().previous(); // Dismiss all showcases ShowcaseView.get().dismiss(); ``` -------------------------------- ### Set Project and Binary Name Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Defines the minimum CMake version and the project name, along with the executable's binary name. ```cmake cmake_minimum_required(VERSION 3.15) project(example LANGUAGES CXX) set(BINARY_NAME "example") ``` -------------------------------- ### Include Flutter Build Rules Source: https://github.com/simformsolutionspvtltd/showcaseview/blob/master/example/windows/CMakeLists.txt Includes the Flutter library and tool build rules from the managed directory and integrates generated plugin build rules. ```cmake set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") # Flutter library and tool build rules. add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build add_subdirectory("runner") # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) ```