🧩 高级功能
版本 PanGrowth
💰 自定义广告完整指南
pangrowth_content插件支持在多个组件中接入自定义广告,让你可以灵活控制广告展示逻辑和样式,实现更高的广告变现收益。
✨ 功能概览
支持自定义广告的组件
组件名 | 支持的广告类型 | 说明 |
---|---|---|
DramaPlayerNativeView | Draw广告、Banner广告 | 短剧播放页自定义广告 |
DramaSwipeFlowNativeView | Draw广告、Banner广告 | 短剧滑滑流自定义广告 |
StoryReaderNativeView | 章间广告、段间广告、Banner广告 | 短故事阅读器自定义广告 |
自定义广告类型说明
1. Draw广告(竖版视频广告)
- 位置: 插入在内容列表中
- 形式: 全屏竖版视频广告
- 适用场景: 短剧播放页、短剧滑滑流
- 配置参数:
drawAdPositions
+customDrawAdViewId
2. Banner广告(横幅广告)
- 位置: 底部横幅区域
- 形式: 固定高度的横幅广告
- 适用场景: 所有支持自定义广告的组件
- 配置参数:
customBannerAdViewId
3. 章间广告(页间广告)
- 位置: 章节切换时显示
- 形式: 全屏广告
- 适用场景: 短故事阅读器
- 配置参数:
customMiddlePageAdViewId
+middlePageInterval
4. 段间广告(行间广告)
- 位置: 段落间插入
- 形式: 行内广告
- 适用场景: 短故事阅读器
- 配置参数:
customMiddleLineAdViewId
+middleLineStartLine
+middleLineInterval
🚀 使用示例
示例1: 短剧播放页自定义广告
import 'package:flutter/material.dart';
import 'package:pangrowth_content/pangrowth_content.dart';
class CustomAdDramaPlayerPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: DramaPlayerNativeView(
config: DramaPlayerConfig(
dramaId: 12345,
episode: 1,
// 配置Draw广告位置
drawAdPositions: [3, 6, 9], // 在第3、6、9集插入Draw广告
customDrawAdViewId: 'my_draw_ad', // 自定义Draw广告视图ID
customBannerAdViewId: 'my_banner_ad', // 自定义Banner广告视图ID
),
listener: DramaPlayerListener(
onPlayerReady: (playerId) {
print('播放器就绪: $playerId');
},
),
),
);
}
}
说明:
drawAdPositions
: 指定在哪些集数插入Draw广告customDrawAdViewId
: 自定义Draw广告视图的唯一标识customBannerAdViewId
: 自定义Banner广告视图的唯一标识- 原生层会根据viewId创建对应的广告视图并显示
示例2: 短剧滑滑流自定义广告
import 'package:flutter/material.dart';
import 'package:pangrowth_content/pangrowth_content.dart';
class CustomAdTheaterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: DramaSwipeFlowNativeView(
config: DramaSwipeFlowConfig(
channelType: 1,
detailFree: 5,
unlockCount: 1,
// 配置自定义广告
drawAdPositions: [5, 10, 15], // 每5个短剧插入一次Draw广告
customDrawAdViewId: 'theater_draw_ad',
customBannerAdViewId: 'theater_banner_ad',
),
listener: DramaSwipeFlowListener(
onSwipeFlowReady: (swipeFlowId) {
print('滑滑流就绪: $swipeFlowId');
},
),
),
);
}
}
示例3: 短故事阅读器自定义广告
import 'package:flutter/material.dart';
import 'package:pangrowth_content/pangrowth_content.dart';
class CustomAdStoryReaderPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: StoryReaderNativeView(
config: StoryReaderConfig(
storyId: 67890,
startChapter: 0,
// 配置章间广告
customMiddlePageAdViewId: 'story_page_ad',
middlePageInterval: 5, // 每5章插入一次章间广告
// 配置段间广告
customMiddleLineAdViewId: 'story_line_ad',
middleLineStartLine: 10, // 从第10行开始插入段间广告
middleLineInterval: 20, // 每20行插入一次段间广告
// 配置Banner广告
customBannerAdViewId: 'story_banner_ad',
),
listener: StoryReaderListener(
onReaderReady: (readerId) {
print('阅读器就绪: $readerId');
},
onMiddlePageAdShow: () {
print('章间广告显示');
},
onMiddleLineAdShow: (lineNumber) {
print('段间广告显示在第$lineNumber行');
},
),
),
);
}
}
🎨 自定义广告Widget示例
原生层需要根据提供的viewId创建对应的广告视图。以下是几种常见广告Widget的示例:
Banner广告Widget
class MyBannerAdWidget extends StatelessWidget {
const MyBannerAdWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 50,
color: Colors.blue,
child: Center(
child: Text(
'自定义Banner广告',
style: TextStyle(color: Colors.white),
),
),
);
}
}
Draw广告Widget
class MyDrawAdWidget extends StatelessWidget {
const MyDrawAdWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
child: Stack(
children: [
// 广告视频播放器
Center(
child: AspectRatio(
aspectRatio: 9 / 16,
child: Container(
color: Colors.grey[800],
child: Icon(
Icons.play_circle_outline,
size: 64,
color: Colors.white,
),
),
),
),
// 跳过按钮
Positioned(
top: 40,
right: 20,
child: TextButton(
onPressed: () {
// 跳过广告逻辑
},
style: TextButton.styleFrom(
backgroundColor: Colors.black54,
),
child: Text(
'跳过 5s',
style: TextStyle(color: Colors.white),
),
),
),
],
),
);
}
}
章间广告Widget
class MyMiddlePageAdWidget extends StatelessWidget {
final VoidCallback? onClose;
const MyMiddlePageAdWidget({Key? key, this.onClose}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Stack(
children: [
// 广告内容
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.ad_units, size: 100, color: Colors.blue),
SizedBox(height: 20),
Text(
'章间广告',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('查看广告可解锁更多内容'),
],
),
),
// 关闭按钮
Positioned(
top: 40,
right: 20,
child: IconButton(
icon: Icon(Icons.close, color: Colors.black),
onPressed: onClose,
),
),
],
),
);
}
}
💡 最佳实践
1. 广告位置优化
Draw广告插入位置:
// ✅ 推荐:合理间隔,避免影响用户体验
drawAdPositions: [5, 10, 15, 20]
// ❌ 不推荐:过于频繁
drawAdPositions: [1, 2, 3, 4, 5]
章间广告间隔:
// ✅ 推荐:每3-5章插入一次
middlePageInterval: 5
// ❌ 不推荐:每章都插入
middlePageInterval: 1
2. 广告加载优化
- 预加载广告数据,减少等待时间
- 使用占位符避免布局闪烁
- 失败时优雅降级,不影响内容浏览
3. 用户体验优化
- 提供"跳过广告"按钮
- 明确显示广告剩余时间
- 避免强制观看过长的广告
- 提供广告反馈入口
4. 性能优化
// 使用Controller管理广告生命周期
class MyAdPage extends StatefulWidget {
@override
_MyAdPageState createState() => _MyAdPageState();
}
class _MyAdPageState extends State<MyAdPage> {
final _controller = DramaPlayerController();
@override
void dispose() {
// ✅ 重要:销毁时释放资源
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DramaPlayerNativeView(
controller: _controller,
config: DramaPlayerConfig(
dramaId: 12345,
episode: 1,
customBannerAdViewId: 'my_ad',
),
);
}
}
⚠️ 注意事项
1. ViewID唯一性
- 每个自定义广告视图必须使用唯一的viewId
- 不同组件的广告可以使用不同的viewId
- 建议使用描述性命名,如
'drama_player_banner'
、'story_reader_page_ad'
2. 原生层实现
- 自定义广告需要在原生层(Android/iOS)实现对应的广告Provider
- 原生层会根据viewId查找并创建对应的广告视图
- 具体实现请参考原生层文档
3. 广告视图生命周期
- 广告视图随NativeView一起创建和销毁
- 确保广告资源在dispose时正确释放
- 避免内存泄漏
4. 平台差异
- 某些配置参数可能仅在特定平台生效
- Android和iOS的广告Provider接口可能略有差异
- 测试时需要覆盖两个平台
❓ 常见问题
Q: 自定义广告不显示怎么办?
A: 检查以下几点:
- 确认viewId已正确配置
- 检查原生层是否实现了对应的AdProvider
- 查看日志是否有错误信息
- 确认SDK已正确初始化
Q: 可以同时使用SDK广告和自定义广告吗?
A: 可以。如果不配置自定义广告参数,组件会使用SDK默认广告。你可以只自定义部分广告类型,其他使用SDK默认。
Q: 如何统计自定义广告的曝光和点击?
A: 使用Listener监听广告事件:
StoryReaderListener(
onMiddlePageAdShow: () {
// 统计章间广告曝光
Analytics.logEvent('ad_show', {'type': 'middle_page'});
},
onMiddlePageAdClick: () {
// 统计章间广告点击
Analytics.logEvent('ad_click', {'type': 'middle_page'});
},
)
Q: 原生层如何获取自定义广告视图?
A: 原生层通过实现对应的AdProvider接口,根据Flutter传递的viewId创建广告视图:
- Android: 实现
IDJXDramaAdCustomProvider
、INovMiddlePageAdProvider
等接口 - iOS: 实现相应的Delegate协议
详细的原生层实现请参考Flutter插件开发文档。
🔗 相关文档
- 短剧播放页 - NativeView / API 指南
- 短剧滑滑流 - NativeView / API 指南
- 短故事阅读器 - 阅读器 NativeView / API 指南
- Widget组件总览 - 所有组件导航