如何在ExoPlayer 2.7.1控制器中展示指定时间间隔的广告标记?
在ExoPlayer 2.7.1控制器中添加广告标记的实现方案
嘿,针对你用ExoPlayer 2.7.1在视频控制器上展示特定时间点广告标记的需求,我给你整理了一套适配这个版本的可行方案,步骤很清晰:
1. 自定义带广告标记的进度条
核心思路是重写进度条(SeekBar)的绘制逻辑,在进度条上根据广告时间数组绘制标记点。创建一个AdMarkSeekBar类继承自AppCompatSeekBar:
public class AdMarkSeekBar extends AppCompatSeekBar { private long[] adTimestamps; // 存储广告时间的毫秒数组 private Paint adMarkPaint; private int markRadius = 4; // 标记点的半径,可按需调整 public AdMarkSeekBar(Context context) { super(context); init(); } public AdMarkSeekBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { adMarkPaint = new Paint(); adMarkPaint.setColor(Color.RED); // 标记点颜色,可自定义 adMarkPaint.setAntiAlias(true); } // 设置广告时间数组 public void setAdTimestamps(long[] timestamps) { this.adTimestamps = timestamps; invalidate(); // 触发重绘 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (adTimestamps == null || adTimestamps.length == 0 || getMax() == 0) { return; } long videoDuration = getMax(); int seekBarWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int seekBarHeight = getHeight() / 2; // 标记点垂直居中 for (long adTime : adTimestamps) { if (adTime < 0 || adTime > videoDuration) { continue; // 跳过无效时间点 } // 计算标记点在进度条上的水平位置 float positionPercent = (float) adTime / videoDuration; int markX = getPaddingLeft() + (int) (positionPercent * seekBarWidth); // 绘制圆形标记点 canvas.drawCircle(markX, seekBarHeight, markRadius, adMarkPaint); } } }
2. 替换ExoPlayer默认控制器的进度条
ExoPlayer 2.7.1的默认控制器是PlaybackControlView,它的布局里进度条的id是R.id.exo_progress。我们需要把这个默认的SeekBar替换成自定义的AdMarkSeekBar:
方式一:通过代码替换
在初始化SimpleExoPlayerView的地方,找到控制器里的进度条并替换:
SimpleExoPlayerView playerView = findViewById(R.id.player_view); PlaybackControlView controlView = playerView.findViewById(R.id.exo_controller); SeekBar defaultSeekBar = controlView.findViewById(R.id.exo_progress); // 移除默认进度条,添加自定义进度条 ViewGroup parent = (ViewGroup) defaultSeekBar.getParent(); int index = parent.indexOfChild(defaultSeekBar); parent.removeView(defaultSeekBar); AdMarkSeekBar adMarkSeekBar = new AdMarkSeekBar(this); // 复制默认进度条的布局参数 LayoutParams params = defaultSeekBar.getLayoutParams(); parent.addView(adMarkSeekBar, index, params); // 关联播放器和自定义进度条 playerView.setSeekBar(adMarkSeekBar);
方式二:自定义控制器布局
如果你的项目已经用了自定义的控制器布局,直接把布局里的SeekBar换成AdMarkSeekBar即可,比如:
<com.yourpackage.AdMarkSeekBar android:id="@id/exo_progress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:maxHeight="4dp" android:minHeight="4dp" android:progressDrawable="@drawable/exo_progress_bar" android:thumb="@drawable/exo_progress_thumb"/>
然后在代码中设置控制器布局:
playerView.setControllerLayoutId(R.layout.your_custom_controller);
3. 传递广告时间并更新标记
当视频加载完成、时长确定后,把广告时间数组传递给自定义进度条,同时监听播放器的时间线变化,确保标记点能正确更新:
// 假设你的广告时间数组是这样的 long[] adTimes = {10000, 30000, 60000}; // 10秒、30秒、60秒处的广告标记 // 获取自定义进度条实例 AdMarkSeekBar adMarkSeekBar = controlView.findViewById(R.id.exo_progress); // 监听播放器的时间线变化,当时长可用时更新标记 player.addListener(new Player.DefaultEventListener() { @Override public void onTimelineChanged(Timeline timeline, Object manifest) { super.onTimelineChanged(timeline, manifest); if (timeline != null && timeline.getWindowCount() > 0) { long duration = timeline.getWindow(0, new Timeline.Window()).getDurationMs(); if (duration != C.TIME_UNSET) { adMarkSeekBar.setMax((int) duration); adMarkSeekBar.setAdTimestamps(adTimes); } } } });
注意事项
- 确保广告时间数组里的时间戳不超过视频总时长,否则标记点会被忽略(代码里已经做了判断)
- 可以根据需求调整标记点的大小、颜色、形状(比如改成矩形)
- 如果播放器支持倍速播放,标记点的位置不需要额外调整,因为我们是基于总时长的比例计算的
内容的提问来源于stack exchange,提问作者khateeb
相关产品推荐
相关产品推荐

