Links

Video Feed

Currently, there are eight source types of the video feed:
  • Discover
  • Channel
  • Playlist
  • Playlist Group(Only supported on iOS)
  • Dynamic Content
  • Hashtag Playlist
  • SKU
  • Single Content

Integration

import 'package:fw_flutter_sdk/fw_flutter_sdk.dart';
/// discover
VideoFeed(
height: 200,
source: VideoFeedSource.discover,
);
/// channel
VideoFeed(
height: 200,
source: VideoFeedSource.channel,
channel: "your encoded channel id",
);
/// playlist
VideoFeed(
height: 200,
source: VideoFeedSource.playlist,
playlist: "your encoded playlist id",
channel: "your encoded channel id",
);
/// playlist group
VideoFeed(
height: 200,
source: VideoFeedSource.playlistGroup,
playlistGroup: "your encoded playlist group id",
);
/// dynamic content
VideoFeed(
height: 200,
source: VideoFeedSource.dynamicContent,
dynamicContentParameters: const {
'<cohort key>': ['<cohort value1>', '<cohort value2>']
},
);
/// hashtag playlist
VideoFeed(
height: 200,
source: VideoFeedSource.hashtagPlaylist,
channel: "your encoded channel id",
hashtagFilterExpression: "<hashtag filter expression>",
);
/// sku playlist
VideoFeed(
height: 200,
source: VideoFeedSource.sku,
channel: "your encoded channel id",
productIds: ["prodct_id_1", "prodct_id_2"],
);
/// single content
VideoFeed(
height: 200,
source: VideoFeedSource.singleContent,
contentId="your encoded video or live stream id"
);
Please refer to the Encoded IDs help article to learn about how to find your encoded channel ID, playlist ID, playlist Group ID

Mode

VideoFeed widget supports three modes: row, column, and grid.
Use grid mode:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: VideoFeed(
source: VideoFeedSource.discover,
mode: VideoFeedMode.grid,
),
)
],
);

Video feed configuration

VideoFeed widget provides videoFeedConfiguration property for configuring Video Feed. The current configurable are backgroundColor, cornerRadius, and titlePosition etc. Please refer to VideoFeedConfiguration for more details.
final videoFeedConfiguration = VideoFeedConfiguration();
videoFeedConfiguration.title = VideoFeedTitleConfiguration();
videoFeedConfiguration.title?.hidden = false;
videoFeedConfiguration.titlePosition = VideoFeedTitlePosition.nested;
videoFeedConfiguration.cornerRadius = 10;
videoFeedConfiguration.itemSpacing = 10;
VideoFeed(
source: VideoFeedSource.discover,
videoFeedConfiguration: videoFeedConfiguration,
);

Video player configuration

VideoFeed widget provides videoPlayerConfiguration property for configuring Video Player. The current configurable properties are playerStyle, videoCompleteAction, and ctaButtonStyle etc. Please refer to VideoPlayerConfiguration for more details.
final videoPlayerConfiguration = VideoPlayerConfiguration();
videoPlayerConfiguration.playerStyle = VideoPlayerStyle.full;
videoPlayerConfiguration.videoCompleteAction = VideoPlayerCompleteAction.advanceToNext;
videoPlayerConfiguration.showShareButton = true;
videoPlayerConfiguration.showMuteButton = true;
videoPlayerConfiguration.showPlaybackButton = true;
VideoFeed(
source: VideoFeedSource.discover,
videoPlayerConfiguration: videoPlayerConfiguration,
);

Video feed loading result callback

VideoFeed widget provides onVideoFeedLoadFinished property for setting video feed loading result callback.
VideoFeed(
source: VideoFeedSource.discover,
onVideoFeedLoadFinished: (error) {},
);

Force refreshing video feed

VideoFeedController? _feedController;
VideoFeed(
source: VideoFeedSource.discover,
onVideoFeedCreated: (controller) {
_feedController = controller;
},
);
//force refreshing video feed
_feedController?.refresh();

Floating Player

You could set enablePictureInPicture to true to enable the floating player.
VideoFeed(
height: 200,
source: VideoFeedSource.discover,
enablePictureInPicture: true,
);

OS Picture in Picture

You also need to set enablePictureInPicture to true to enable the OS Picture in Picture.
VideoFeed(
height: 200,
source: VideoFeedSource.discover,
enablePictureInPicture: true,
);
This feature allows the user to watch media while the application is in a background state. While in background mode a video will display in a floating, resizable window.

Set up the iOS project

To enable PiP functionality, you also need to add Background Modes capability via Signing & Capabilities in your iOS project settings. More information about this can be found here: Apple Documentation
To use Picture in Picture, we configure the app to support background audio playback. See Configuring the Audio Playback of iOS and tvOS Apps for more details.

Keep alive when scrolling the list

Generally, if you put the video feed widget as the child of ListView, it will be rebuilt when scrolling the list. You could refer to the following two ways to make the video feed widget keep alive when scrolling the list.

Replace ListView with SingleChildScrollView and Column

ListView(
children: [
VideoFeed(
source: VideoFeedSource.discover,
),
],
);
// Replace ListView with SingleChildScrollView and Column
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
VideoFeed(
source: VideoFeedSource.discover,
),
],
),
);

Use addAutomaticKeepAlives and AutomaticKeepAliveClientMixin

class VideoFeedWrapper extends StatefulWidget {
final Widget child;
const VideoFeedWrapper({
super.key,
required this.child,
});
@override
State<VideoFeedWrapper> createState() => _VideoFeedWrapperState();
}
class _VideoFeedWrapperState extends State<VideoFeedWrapper>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
super.build(context); // This line is required.
return widget.child;
}
@override
bool get wantKeepAlive => true; // Need to return true.
}
ListView(
addAutomaticKeepAlives: true, // Need to be set to true.
children: [
VideoFeedWrapper(
child: VideoFeed(
source: VideoFeedSource.discover,
),
),
],
);

Reference

VideoFeed