StorytellerEmbeddedClipsView lets you place the native Storyteller clips experience inline within your Flutter UI while keeping full control of layout, scrolling, and lifecycle.
collectionId(required) – the Storyteller collection to play.
clipId – start playback at a specific clip.
initialCategory – open the embedded UI within a category.
openReason – optional analytics attribution using StorytellerOpenReason.instanceMethod or StorytellerOpenReason.deeplink. Omit it to preserve the native Embedded Clips default.
Pre-roll is supported on Android and iOS. Omit the nullable value to preserve
the native default; Android 11.6.3 defaults it on and iOS 11.6.1 defaults it
off. Provider ordering remains Android-only.
All three fields are nullable. Only values you explicitly supply are sent to native
code; the linked native SDK chooses defaults for missing fields. Provider
ordering is supported on Android 11.6.3+ and ignored on iOS. A null order
keeps native module order, an empty list disables standard between-Clips
providers for this presentation, and a populated list restricts and orders
them. Omitting the whole adConfiguration object keeps the native Embedded
Clips defaults for the current platform and SDK version.
For a production-ready configuration (including safe-area handling and controller-driven playback), review the Showcase MomentsScreen.
onDataLoadStarted() – when Storyteller begins loading collection data.
onDataLoadComplete(StorytellerEmbeddedClipsLoadResult result) – includes status and counts; inspect result.error when result.success is false.
onUserActivityOccurred(Map<String, dynamic> payload) – emits the same payloads you see on the global onUserActivityOccurred stream, scoped to this embedded instance.
Attach a StorytellerEmbeddedClipsController to pause/resume playback, update retained-view visibility, reload data, or propagate inset changes after creation.
setIsVisible(bool) – show or hide the retained native platform view without disposing its player state.
updateInsets({int top, int bottom}) – sync safe areas when your layout changes.
Playback and visibility are independent. setShouldPlay(false) keeps an onscreen player rendered in its paused state. For an IndexedStack or another retained tab container, also call setIsVisible(false) when that tab becomes inactive so native view-based ad media receives a real visibility transition. Restore visibility before resuming playback when the tab becomes active again.
Calls made before the platform view is created are ignored (the embedded clips controller does not queue commands). Prefer invoking controller methods after the widget is on screen (for example, after the first frame) or in response to user interaction.
{"slug": "embedded-clips", "page_title": "Embedded Clips", "page_url": "EmbeddedClips/", "canonical_url": "/flutter/EmbeddedClips/", "markdown": "# Embedded Clips\n\n`StorytellerEmbeddedClipsView` lets you place the native Storyteller clips experience inline within your Flutter UI while keeping full control of layout, scrolling, and lifecycle.\n\n## Basic usage\n\n```dart\nclass InlineClips extends StatelessWidget {\n const InlineClips({super.key});\n\n @override\n Widget build(BuildContext context) {\n return SizedBox(\n height: 420,\n child: StorytellerEmbeddedClipsView(\n collectionId: 'featured-highlights',\n openReason: StorytellerOpenReason.instanceMethod,\n shouldPlay: true,\n topLevelBack: false,\n onDataLoadStarted: () => debugPrint('Loading clips...'),\n onDataLoadComplete: (result) {\n debugPrint('Loaded ${result.dataCount} clips');\n },\n ),\n );\n }\n}\n```\n\nKey parameters:\n\n- `collectionId` *(required)* \u2013 the Storyteller collection to play.\n- `clipId` \u2013 start playback at a specific clip.\n- `initialCategory` \u2013 open the embedded UI within a category.\n- `openReason` \u2013 optional analytics attribution using `StorytellerOpenReason.instanceMethod` or `StorytellerOpenReason.deeplink`. Omit it to preserve the native Embedded Clips default.\n- `adConfiguration` \u2013 optional per-presentation `StorytellerClipsAdConfiguration` controlling first-Clip pre-roll, bottom-banner placement, and Android between-Clips provider ordering.\n- `shouldPlay` \u2013 autoplay behaviour (defaults to `true`).\n- `isVisible` \u2013 native platform-view visibility (defaults to `true`). Set this to `false` when retaining the player in an inactive tab.\n- `topLevelBack` \u2013 whether to expose a back button for nested navigation.\n- `theme` \u2013 apply a `StorytellerTheme` override.\n- `context` \u2013 attach analytics context metadata.\n- `topInset` / `bottomInset` \u2013 provide safe area values in logical pixels. Available on Android only.\n\n## Configure ad placements for one presentation\n\nPass an ad configuration only when this Embedded Clips instance needs to\noverride native placement behavior:\n\n```dart\nStorytellerEmbeddedClipsView(\n collectionId: 'featured-highlights',\n adConfiguration: const StorytellerClipsAdConfiguration(\n preRollEnabled: true,\n bottomBannerEnabled: true,\n betweenClipsAdProviderOrder: [\n StorytellerAdProvider.gam,\n StorytellerAdProvider.vast,\n ],\n ),\n)\n```\n\nPre-roll is supported on Android and iOS. Omit the nullable value to preserve\nthe native default; Android 11.6.3 defaults it on and iOS 11.6.1 defaults it\noff. Provider ordering remains Android-only.\n\nAll three fields are nullable. Only values you explicitly supply are sent to native\ncode; the linked native SDK chooses defaults for missing fields. Provider\nordering is supported on Android 11.6.3+ and ignored on iOS. A `null` order\nkeeps native module order, an empty list disables standard between-Clips\nproviders for this presentation, and a populated list restricts and orders\nthem. Omitting the whole `adConfiguration` object keeps the native Embedded\nClips defaults for the current platform and SDK version.\n\nFor a production-ready configuration (including safe-area handling and controller-driven playback), review the Showcase [`MomentsScreen`](https://github.com/getstoryteller/storyteller-showcase-flutter/blob/main/lib/screens/moments/moments_screen.dart#L217).\n\n## React to embedded callbacks\n\nThree callbacks surface native lifecycle events:\n\n- `onDataLoadStarted()` \u2013 when Storyteller begins loading collection data.\n- `onDataLoadComplete(StorytellerEmbeddedClipsLoadResult result)` \u2013 includes status and counts; inspect `result.error` when `result.success` is `false`.\n- `onUserActivityOccurred(Map<String, dynamic> payload)` \u2013 emits the same payloads you see on the global `onUserActivityOccurred` stream, scoped to this embedded instance.\n\n## Control playback programmatically\n\nAttach a `StorytellerEmbeddedClipsController` to pause/resume playback, update retained-view visibility, reload data, or propagate inset changes after creation.\n\n```dart\nclass ControllableEmbeddedClips extends StatefulWidget {\n const ControllableEmbeddedClips({super.key});\n\n @override\n State<ControllableEmbeddedClips> createState() =>\n _ControllableEmbeddedClipsState();\n}\n\nclass _ControllableEmbeddedClipsState\n extends State<ControllableEmbeddedClips> {\n final _controller = StorytellerEmbeddedClipsController();\n\n @override\n Widget build(BuildContext context) {\n return Column(\n children: [\n Expanded(\n child: StorytellerEmbeddedClipsView(\n collectionId: 'live-stream',\n controller: _controller,\n shouldPlay: false,\n ),\n ),\n FilledButton(\n onPressed: () async {\n await _controller.setShouldPlay(true);\n },\n child: const Text('Play clips'),\n ),\n ],\n );\n }\n}\n```\n\nAvailable controller actions:\n\n- `reloadData()` \u2013 refreshes the native data source.\n- `goBack()` / `canGoBack()` \u2013 traverse nested embedded navigation.\n- `setShouldPlay(bool)` \u2013 toggle playback.\n- `setIsVisible(bool)` \u2013 show or hide the retained native platform view without disposing its player state.\n- `updateInsets({int top, int bottom})` \u2013 sync safe areas when your layout changes.\n\nPlayback and visibility are independent. `setShouldPlay(false)` keeps an onscreen player rendered in its paused state. For an `IndexedStack` or another retained tab container, also call `setIsVisible(false)` when that tab becomes inactive so native view-based ad media receives a real visibility transition. Restore visibility before resuming playback when the tab becomes active again.\n\nCalls made before the platform view is created are ignored (the embedded clips controller does not queue commands). Prefer invoking controller methods after the widget is on screen (for example, after the first frame) or in response to user interaction.\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}