🎬 短剧模块
版本 PanGrowth
🎬 短剧滑滑流
短剧滑滑流提供类似抖音的竖向滑动播放体验,支持推荐/剧场频道、广告解锁、播放控制等完整能力。插件同时提供 NativeView 组件 与 API 控制 两条集成路径。
🚪 接入方式概览
方式 | 推荐场景 | 实现特点 |
---|---|---|
NativeView 组件(推荐) | Flutter 页面内嵌滑滑流内容,追求最少代码 | 使用 DramaSwipeFlowNativeView ,自动管理创建/销毁,可配合 DramaSwipeFlowController 与 DramaSwipeFlowListener |
API 调用 | 需要在原生 Activity/ViewController 展示或精确控制生命周期 | 使用 createDramaSwipeFlow / showDramaSwipeFlow / hideDramaSwipeFlow / destroyDramaSwipeFlow 主动控制 |
注意:两种方式的配置对象不同:
- NativeView 方式使用
DramaSwipeFlowConfig
- API 方式使用
DramaSwipeConfig
✅ 方式一:DramaSwipeFlowNativeView
(推荐)
DramaSwipeFlowNativeView
通过 PlatformView 内嵌原生滑滑流,Flutter 层像普通 Widget 一样使用。
基础示例
import 'package:flutter/material.dart';
import 'package:pangrowth_content/pangrowth_content.dart';
class DramaSwipeFlowPage extends StatelessWidget {
const DramaSwipeFlowPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: DramaSwipeFlowNativeView(
config: const DramaSwipeFlowConfig(
channelType: 1, // 推荐频道
detailFree: 5, // 免费 5 集
unlockCount: 1, // 每次解锁 1 集
autoPlay: true, // 自动播放下一集
),
),
);
}
}
结合 DramaSwipeFlowListener
使用 DramaSwipeFlowListener
监听滑滑流生命周期事件:
DramaSwipeFlowNativeView(
config: const DramaSwipeFlowConfig(
channelType: 1,
detailFree: 5,
unlockCount: 1,
),
listener: DramaSwipeFlowListener(
onSwipeFlowReady: (swipeFlowId) {
debugPrint('滑滑流就绪: $swipeFlowId');
},
onSwipeFlowError: (error) {
debugPrint('滑滑流错误: $error');
},
onSwipeFlowDisposed: () {
debugPrint('滑滑流已销毁');
},
onOpenDetail: (drama) {
debugPrint('打开短剧详情: ${drama.title}');
// 可在此处拦截并导航到自定义详情页
},
),
)
结合 DramaSwipeFlowController
当需要在 TabBar 切换等场景控制暂停/恢复时,使用 DramaSwipeFlowController
:
class DramaTabPage extends StatefulWidget {
const DramaTabPage({super.key});
@override
State<DramaTabPage> createState() => _DramaTabPageState();
}
class _DramaTabPageState extends State<DramaTabPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final _swipeFlowController = DramaSwipeFlowController();
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
// 监听Tab切换,自动暂停/恢复
_tabController.addListener(() {
if (_tabController.index == 1) {
_swipeFlowController.resume(); // 切换到滑滑流Tab,恢复播放
} else {
_swipeFlowController.pause(); // 切换走,暂停播放
}
});
}
@override
void dispose() {
_swipeFlowController.dispose();
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: const [
Tab(text: '首页'),
Tab(text: '追剧'), // 滑滑流Tab
Tab(text: '我的'),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
const Center(child: Text('首页')),
DramaSwipeFlowNativeView(
config: const DramaSwipeFlowConfig(
channelType: 3, // 推荐+剧场双频道
detailFree: 5,
unlockCount: 1,
),
controller: _swipeFlowController,
),
const Center(child: Text('我的')),
],
),
);
}
}
配置参数:DramaSwipeFlowConfig
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
频道配置 | |||
channelType | int | 1 | 频道类型:<br/>• 1 - 仅推荐频道<br/>• 2 - 仅剧场频道<br/>• 3 - 推荐+剧场双频道 |
解锁配置 | |||
detailFree | int | 5 | 免费观看集数 |
unlockCount | int | 1 | 每次观看广告解锁的集数 |
unlockAdMode | int | 0 | 解锁广告模式:<br/>• 0 - SDK默认解锁(使用SDK内置广告)<br/>• 1 - 自定义解锁(需监听解锁事件,自行处理) |
UI控制 | |||
hideTopInfo | bool | false | 是否隐藏顶部信息区域 |
setTopOffset | int? | null | 顶部信息偏移量(dp) |
hideBottomInfo | bool | false | 是否隐藏底部信息区域 |
setBottomOffset | int? | null | 底部信息偏移量(dp) |
hideEnter | bool | false | 是否隐藏进入(下一集)按钮 |
hideLikeButton | bool | false | 是否隐藏点赞按钮 |
hideFavorButton | bool | false | 是否隐藏收藏按钮 |
showChangeBtn | bool | true | 是否显示"换一换"按钮 |
hideBack | bool | true | 是否隐藏返回按钮 |
播放配置 | |||
autoPlay | bool | true | 是否自动播放下一集 |
自定义广告 | |||
drawAdPositions | List<int>? | null | Draw广告插入位置数组,如 [3, 6, 9] 表示在第3、6、9个位置插入 |
customDrawAdViewId | String? | null | 自定义Draw广告视图ID |
customBannerAdViewId | String? | null | 自定义Banner广告视图ID |
生命周期管理
DramaSwipeFlowNativeView
自动管理滑滑流生命周期:
- 创建: Widget
initState
时自动创建原生视图 - 显示: Widget
build
时自动显示 - 销毁: Widget
dispose
时自动销毁原生视图
手动销毁场景:如果需要在 Widget 存活期间销毁滑滑流,使用 DramaSwipeFlowController
:
final controller = DramaSwipeFlowController();
// 手动销毁
await controller.dispose();
🧭 方式二:API 控制
适合需要精确控制滑滑流生命周期的场景,如原生 Activity/ViewController 中展示。
完整生命周期演示
import 'package:flutter/material.dart';
import 'package:pangrowth_content/pangrowth_content.dart';
class DramaSwipeFlowAPIDemo extends StatefulWidget {
const DramaSwipeFlowAPIDemo({super.key});
@override
State<DramaSwipeFlowAPIDemo> createState() => _DramaSwipeFlowAPIDemoState();
}
class _DramaSwipeFlowAPIDemoState extends State<DramaSwipeFlowAPIDemo> {
String? _widgetId;
Future<void> _createAndShow() async {
// 1. 创建滑滑流
final config = DramaSwipeConfig(
channelType: 1,
dramaFree: 5,
unlockEpisodesCount: 1,
progressBarStyle: 1,
);
final result = await PangrowthContent.createDramaSwipeFlow(config: config);
if (result['success'] == true) {
_widgetId = result['widgetId'] as String;
debugPrint('创建成功: $_widgetId');
// 2. 显示滑滑流
await PangrowthContent.showDramaSwipeFlow(_widgetId!);
debugPrint('显示成功');
}
}
Future<void> _hide() async {
if (_widgetId != null) {
await PangrowthContent.hideDramaSwipeFlow(_widgetId!);
debugPrint('隐藏成功');
}
}
Future<void> _destroy() async {
if (_widgetId != null) {
await PangrowthContent.destroyDramaSwipeFlow(_widgetId!);
debugPrint('销毁成功');
setState(() {
_widgetId = null;
});
}
}
@override
void dispose() {
// 清理资源
if (_widgetId != null) {
PangrowthContent.destroyDramaSwipeFlow(_widgetId!);
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('API方式演示')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _widgetId == null ? _createAndShow : null,
child: const Text('创建并显示'),
),
ElevatedButton(
onPressed: _widgetId != null ? _hide : null,
child: const Text('隐藏'),
),
ElevatedButton(
onPressed: _widgetId != null ? _destroy : null,
child: const Text('销毁'),
),
],
),
),
);
}
}
配置参数:DramaSwipeConfig
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
布局配置 | |||
bottomOffset | int? | null | 底部偏移量(dp) |
titleTopMargin | int? | null | 标题栏上边距(dp) |
titleLeftMargin | int? | null | 标题栏左边距(dp) |
titleRightMargin | int? | null | 标题栏右边距(dp) |
界面控制 | |||
hideChannelName | bool? | null | 是否隐藏频道名称 |
hideDramaInfo | bool? | null | 是否隐藏底部短剧信息 |
hideDramaEnter | bool? | null | 是否隐藏底部短剧入口 |
hideClose | bool? | null | 是否隐藏关闭按钮 |
enableRefresh | bool? | null | 是否支持下拉刷新 |
hideLikeButton | bool? | null | 是否隐藏点赞按钮 |
hideFavorButton | bool? | null | 是否隐藏收藏按钮 |
hideDoubleClickLike | bool? | null | 是否禁止双击点赞 |
样式配置 | |||
progressBarStyle | int? | null | 播放器进度条样式:<br/>• 1 - 浅色进度条(适合深色背景)<br/>• 2 - 深色进度条(适合浅色背景) |
customCategory | String? | null | 自定义推荐频道名称 |
内容配置 | |||
dramaFree | int? | null | 短剧免费集数 |
unlockEpisodesCount | int? | null | 每次解锁的集数(观看广告后解锁的集数) |
topDramaId | int? | null | 短剧置顶ID |
频道配置 | |||
channelType | int? | null | 频道类型:<br/>• 1 - 仅推荐<br/>• 2 - 仅剧场<br/>• 3 - 推荐+剧场 |
contentType | int? | null | 仅Android支持<br/>内容类型:• 1 - 仅显示短剧内容<br/>iOS平台会忽略此参数 |
业务场景示例
新用户场景
final config = DramaSwipeConfig(
hideChannelName: false, // 显示频道名称,引导新用户
hideDramaInfo: false, // 显示详细信息
enableRefresh: true, // 支持下拉刷新
progressBarStyle: 1, // 浅色进度条
dramaFree: 3, // 新用户免费3集
unlockEpisodesCount: 1, // 每次解锁1集
channelType: 1, // 推荐频道
customCategory: '新人推荐',
);
final result = await PangrowthContent.createDramaSwipeFlow(config: config);
VIP用户场景
final config = DramaSwipeConfig(
hideChannelName: true, // 简洁界面
hideDramaInfo: false, // 保留基础信息
enableRefresh: true,
progressBarStyle: 2, // 深色进度条,更高端
dramaFree: 999, // VIP用户免费无限制
unlockEpisodesCount: 1,
channelType: 3, // 推荐+剧场双频道
customCategory: 'VIP专享',
hideLikeButton: false, // 保留社交功能
hideFavorButton: false,
);
final result = await PangrowthContent.createDramaSwipeFlow(config: config);
简洁模式
final config = DramaSwipeConfig(
hideChannelName: true, // 隐藏频道名
hideDramaInfo: true, // 隐藏底部信息
hideLikeButton: true, // 隐藏点赞
hideFavorButton: true, // 隐藏收藏
hideClose: false, // 保留关闭按钮
progressBarStyle: 1,
dramaFree: 5,
channelType: 1,
);
final result = await PangrowthContent.createDramaSwipeFlow(config: config);
🌍 平台差异
Android 专属参数
以下参数仅在 Android 平台生效,iOS 会安全忽略:
DramaSwipeConfig.contentType
- 内容类型筛选
跨平台通用参数
以下参数在 Android 和 iOS 双端都支持:
- 所有
hide*
系列参数(UI控制) channelType
、dramaFree
、unlockEpisodesCount
(业务配置)progressBarStyle
(样式配置)enableRefresh
、autoPlay
(交互配置)
💡 最佳实践
推荐使用 NativeView 方式
除非有特殊需求,否则推荐使用 DramaSwipeFlowNativeView
,理由:
- ✅ 自动管理生命周期,减少内存泄漏风险
- ✅ 代码更简洁,符合 Flutter 开发习惯
- ✅ 与 Flutter Widget 树完美集成
- ✅ 支持
DramaSwipeFlowController
和DramaSwipeFlowListener
配置参数选择建议
- 只传递需要修改的参数:SDK 会为未传递的参数使用原生默认值
- 优先使用通用参数:避免使用平台专属参数,确保跨平台一致性
- 合理设置免费集数:
- 新用户:2-3集(引导转化)
- 普通用户:5集(标准体验)
- VIP用户:999集(无限免费)
性能优化建议
- TabBar 场景必须暂停:切换 Tab 时使用
DramaSwipeFlowController.pause()
暂停播放 - 及时销毁:页面退出时确保调用
dispose()
或destroyDramaSwipeFlow()
- 避免频繁创建销毁:如需隐藏后再显示,使用
hide()
而非destroy()
错误处理
// NativeView方式
DramaSwipeFlowNativeView(
config: config,
listener: DramaSwipeFlowListener(
onSwipeFlowError: (error) {
// 显示错误提示
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('加载失败: $error')),
);
},
),
)
// API方式
try {
final result = await PangrowthContent.createDramaSwipeFlow(config: config);
if (result['success'] != true) {
debugPrint('创建失败');
}
} catch (e) {
debugPrint('异常: $e');
}