The Flutter SDK uses Dart Streams to deliver Storyteller events to your app. You subscribe to event streams provided by the Storyteller class to handle events throughout your app. This stream-based approach replaces the delegate pattern used in native iOS and Android SDKs.
You can subscribe to the following optional event streams to handle Storyteller events:
Need a full reference implementation? The Showcase StorytellerService._setupEventListeners attaches listeners for every stream below and forwards the payloads to its router/logging hooks.
The onUserActivityOccurred stream emits events when analytics events are triggered within the SDK. This allows your app to observe and potentially forward these events to your own analytics systems. See the Analytics page for details on event types and data.
Type:Stream<StorytellerUserActivityEvent>
Example:
Storyteller.onUserActivityOccurred.listen((event){print('Activity: ${event.type}');print('Data: ${event.data}');// Forward to your analytics system});
The userNavigatedToApp stream emits URLs when a user presses an action button on a page which should direct them to a specific place within your app.
Type:Stream<String>
Example:
Storyteller.userNavigatedToApp.listen((url){print('Navigate to: $url');// Handle navigation using your app's routing system// Example: Navigator.pushNamed(context, url);});
See Deep Linking for deep link handling patterns and how to route these URLs.
The categoryFollowActionTaken stream emits events when a user follows or unfollows a category of clips (the category can represent a player, a team, etc.) from within the SDK's UI.
Type:Stream<CategoryFollowEvent>
The CategoryFollowEvent contains:
- category - An object representing the clip category
- isFollowing - A boolean value indicating whether the user is following or unfollowing the specified category
Example:
Storyteller.categoryFollowActionTaken.listen((event){print('Category ${event.category.name} followed: ${event.isFollowing}');if(event.isFollowing){// Add the category to your list of followed categories}else{// Remove the category from your list of followed categories}});
The onShareButtonTapped stream emits share payloads when custom share handling is enabled. Call Storyteller.setUseCustomShareHandling(true) before presenting Storyteller content, then show your own share UI when the stream emits.
Type:Stream<StorytellerShareEvent>
The StorytellerShareEvent contains:
- text - The share text generated by Storyteller
- title - The share title, or an empty string when Storyteller provides none
- url - The share URL, or an empty string when Storyteller provides none
Example:
awaitStoryteller.setUseCustomShareHandling(true);Storyteller.onShareButtonTapped.listen((event){print('Share title: ${event.title}');print('Share url: ${event.url}');// Present your own share flow.});
The onPlayerPresented stream emits an event when a story or clip player is about to be presented on screen. This can be useful for pausing background audio, videos, or animations in your app while the player is visible.
Type:Stream<void>
Example:
Storyteller.onPlayerPresented.listen((_){print('Player is being presented');// Pause your app's media playback});
The onPlayerDismissed stream emits an event when a story or clip player has been dismissed from screen. This can be useful for resuming background audio, videos, or animations in your app that were paused when the player was presented.
Type:Stream<void>
Example:
Storyteller.onPlayerDismissed.listen((_){print('Player was dismissed');// Resume your app's media playback// audioPlayer.resume();});
For handling events specific to StorytellerStoriesRowView and StorytellerStoriesGridView widgets, please refer to the StorytellerListViews documentation for details on widget-specific callbacks like:
- onDataLoadStarted
- onDataLoadComplete
- onTileTapped
- onPlayerDismissed
{"slug": "storyteller-delegate", "page_title": "Event Streams", "page_url": "StorytellerDelegate/", "canonical_url": "/flutter/StorytellerDelegate/", "markdown": "# Implementing Storyteller Delegate Callbacks\n\nThe Flutter SDK uses Dart `Stream`s to deliver Storyteller events to your app. You subscribe to event streams provided by the `Storyteller` class to handle events throughout your app. This stream-based approach replaces the delegate pattern used in native iOS and Android SDKs.\n\n## Available Event Streams\n\nYou can subscribe to the following optional event streams to handle Storyteller events:\n\nNeed a full reference implementation? The Showcase [`StorytellerService._setupEventListeners`](https://github.com/getstoryteller/storyteller-showcase-flutter/blob/main/lib/services/storyteller_service.dart#L161) attaches listeners for every stream below and forwards the payloads to its router/logging hooks.\n\n### onUserActivityOccurred\n\nThe `onUserActivityOccurred` stream emits events when analytics events are triggered within the SDK. This allows your app to observe and potentially forward these events to your own analytics systems. See the [Analytics](Analytics.md) page for details on event types and data.\n\n**Type:** `Stream<StorytellerUserActivityEvent>`\n\n**Example:**\n```dart\nStoryteller.onUserActivityOccurred.listen((event) {\n print('Activity: ${event.type}');\n print('Data: ${event.data}');\n // Forward to your analytics system\n});\n```\n\n### userNavigatedToApp\n\nThe `userNavigatedToApp` stream emits URLs when a user presses an action button on a page which should direct them to a specific place within your app. \n\n**Type:** `Stream<String>`\n\n**Example:**\n```dart\nStoryteller.userNavigatedToApp.listen((url) {\n print('Navigate to: $url');\n // Handle navigation using your app's routing system\n // Example: Navigator.pushNamed(context, url);\n});\n```\n\nSee [Deep Linking](Deeplinking.md) for deep link handling patterns and how to route these URLs.\n\n### categoryFollowActionTaken\n\nThe `categoryFollowActionTaken` stream emits events when a user follows or unfollows a category of clips (the category can represent a player, a team, etc.) from within the SDK's UI.\n\n**Type:** `Stream<CategoryFollowEvent>`\n\nThe `CategoryFollowEvent` contains:\n- `category` - An object representing the clip category\n- `isFollowing` - A boolean value indicating whether the user is following or unfollowing the specified category\n\n**Example:**\n```dart\nStoryteller.categoryFollowActionTaken.listen((event) {\n print('Category ${event.category.name} followed: ${event.isFollowing}');\n \n if (event.isFollowing) {\n // Add the category to your list of followed categories\n } else {\n // Remove the category from your list of followed categories\n }\n});\n```\n\n### onShareButtonTapped\n\nThe `onShareButtonTapped` stream emits share payloads when custom share handling is enabled. Call `Storyteller.setUseCustomShareHandling(true)` before presenting Storyteller content, then show your own share UI when the stream emits.\n\n**Type:** `Stream<StorytellerShareEvent>`\n\nThe `StorytellerShareEvent` contains:\n- `text` - The share text generated by Storyteller\n- `title` - The share title, or an empty string when Storyteller provides none\n- `url` - The share URL, or an empty string when Storyteller provides none\n\n**Example:**\n```dart\nawait Storyteller.setUseCustomShareHandling(true);\n\nStoryteller.onShareButtonTapped.listen((event) {\n print('Share title: ${event.title}');\n print('Share url: ${event.url}');\n // Present your own share flow.\n});\n```\n\n### onPlayerPresented\n\nThe `onPlayerPresented` stream emits an event when a story or clip player is about to be presented on screen. This can be useful for pausing background audio, videos, or animations in your app while the player is visible.\n\n**Type:** `Stream<void>`\n\n**Example:**\n```dart\nStoryteller.onPlayerPresented.listen((_) {\n print('Player is being presented');\n // Pause your app's media playback\n});\n```\n\n### onPlayerDismissed\n\nThe `onPlayerDismissed` stream emits an event when a story or clip player has been dismissed from screen. This can be useful for resuming background audio, videos, or animations in your app that were paused when the player was presented.\n\n**Type:** `Stream<void>`\n\n**Example:**\n```dart\nStoryteller.onPlayerDismissed.listen((_) {\n print('Player was dismissed');\n // Resume your app's media playback\n // audioPlayer.resume();\n});\n```\n\n### onLog\n\nThe `onLog` stream emits debug log messages from the Storyteller SDK. This can be useful for debugging and monitoring SDK behavior.\n\n**Type:** `Stream<String>`\n\n**Example:**\n```dart\nStoryteller.onLog.listen((message) {\n print('Storyteller SDK Log: $message');\n // Forward to your logging system\n});\n```\n\n## StorytellerListView Delegate\n\nFor handling events specific to `StorytellerStoriesRowView` and `StorytellerStoriesGridView` widgets, please refer to the [StorytellerListViews](StorytellerListViews.md) documentation for details on widget-specific callbacks like:\n- `onDataLoadStarted`\n- `onDataLoadComplete`\n- `onTileTapped`\n- `onPlayerDismissed`\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}