Android中禁用ExoPlayer进度条的向前拖动功能
解决ExoPlayer限制仅能向后拖动/跳转进度条的问题
方案一:拦截Player的所有Seek请求(最彻底)
通过包装ExoPlayer实例,重写seekTo方法统一拦截所有向前跳转的请求,无论触发来源是进度条操作还是代码调用,能覆盖所有场景,完全禁止向前跳转。
代码实现
class ForwardSeekRestrictedPlayer(private val delegate: ExoPlayer) : ExoPlayer by delegate { override fun seekTo(positionMs: Long) { val currentPlayPosition = delegate.currentPosition // 仅允许跳转到当前播放位置或更靠前的位置(向后跳转) if (positionMs <= currentPlayPosition) { delegate.seekTo(positionMs) } } override fun seekTo(windowIndex: Int, positionMs: Long) { val currentPlayPosition = delegate.currentPosition if (positionMs <= currentPlayPosition) { delegate.seekTo(windowIndex, positionMs) } } }
使用方式
将原来的ExoPlayer实例替换为包装后的实例:
val realPlayer = ExoPlayer.Builder(context).build() val restrictedPlayer = ForwardSeekRestrictedPlayer(realPlayer) playerView.player = restrictedPlayer
方案二:UI层拦截TimeBar触摸事件(仅限制进度条操作)
如果只需要限制进度条的拖动/点击操作,不影响代码中的seek逻辑,可以直接给DefaultTimeBar设置触摸监听器,在事件传递前拦截向前跳转的操作,响应更及时,解决原方案的延迟问题。
代码实现
val timeBar: DefaultTimeBar? = localPlayerView?.findViewById(R.id.exo_progress) as? DefaultTimeBar val player = localPlayerView?.player ?: return timeBar?.setOnTouchListener { v, event -> val timeBarView = v as DefaultTimeBar val currentPosition = player.currentPosition val duration = timeBarView.duration if (duration <= 0) return@setOnTouchListener false val touchX = event.x val totalWidth = timeBarView.width.toFloat() // 计算触摸位置对应的目标进度 val targetPosition = (touchX / totalWidth * duration).toLong() when (event.action) { MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP -> { // 若目标位置大于当前播放位置,拦截触摸事件 return@setOnTouchListener targetPosition > currentPosition } else -> return@setOnTouchListener false } }
原方案的问题分析
你之前通过TimeBar.OnScrubListener实现的方案存在以下缺陷:
- 响应延迟:
OnScrubListener的回调在TimeBar默认处理触摸事件之后触发,拦截动作有明显延迟; - 位置不准确:
onScrubStart获取的是TimeBar处理后的位置,并非用户初始触摸位置,导致判断逻辑失效; - 无法拦截点击:用户点击进度条向前跳转时,可能直接触发Player的seek操作,跳过ScrubListener的拦截逻辑。
内容的提问来源于stack exchange,提问作者Ludiras
相关产品推荐
相关产品推荐

