Android VideoView 跳回过去
Android VideoView jumps back in time
我已经 videoView
实现了自定义搜索栏。更改搜索栏位置时,视频播放正确但时间显示错误。发生这种情况是因为 videoView
位置由于某种原因返回。它不会总是发生,但经常发生。
SeekBar 变化:
binding.progressBarVideo.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (underSeek) {
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
binding.videoViewF.seekTo(seekBar.progress)
RLog.d("------------------")
RLog.d("Seekbar progress: ${seekBar.progress}")
RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
mainHandler.removeCallbacks(updateTextTask)
underSeek = true
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
mainHandler.post(updateTextTask)
underSeek = false
hideTimer = 0
}
})
更新文本任务:
private val updateTextTask = object : Runnable {
override fun run() {
RLog.d("----------------------------")
RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
binding.progressBarVideo.progress = binding.videoViewF.currentPosition
mainHandler.postDelayed(this, 1000)
}
}
格式持续时间:
@SuppressLint("DefaultLocale")
private fun durationToFormat(duration: Int): String {
return java.lang.String.format(
"%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(duration.toLong()),
TimeUnit.MILLISECONDS.toSeconds(duration.toLong()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration.toLong()))
)
}
日志:
#onProgressChanged: ------------------
#onProgressChanged: Seekbar progress: 257875
#onProgressChanged: videoView position: 257875
#onProgressChanged: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 257875
#run: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 256957
#run: Time display string: 04:16
#run: ----------------------------
可以看到,seek后时间是257875,timer第一次迭代也是257875,然后跳到256957,不明白为什么...
我不确定,但我想问题出在 postDelayed,因为它实际上 运行 在 1 秒后。所以尝试在这里添加 1000 毫秒,希望它能正确运行。
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition + 1000)}")
您似乎从 runnable 再次更新进度,因此将从循环中调用 onProgressChanged 并将进度重置到之前的位置。
在这种情况下,您可以从代码中过滤掉进度更新,并且仅当 fromUser
为 true
时才在 onProgressChanged:
中寻找新的视频位置
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
binding.videoViewF.seekTo(seekBar.progress)
}
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
}
private val updateTextTask = object : Runnable {
override fun run() {
binding.progressBarVideo.progress = binding.videoViewF.currentPosition
mainHandler.postDelayed(this, 1000)
}
}
同样在这种情况下,您可以从 runnable 中删除文本更新,因为它将由 ProgressBar 位置更新触发。
我已经 videoView
实现了自定义搜索栏。更改搜索栏位置时,视频播放正确但时间显示错误。发生这种情况是因为 videoView
位置由于某种原因返回。它不会总是发生,但经常发生。
SeekBar 变化:
binding.progressBarVideo.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (underSeek) {
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
binding.videoViewF.seekTo(seekBar.progress)
RLog.d("------------------")
RLog.d("Seekbar progress: ${seekBar.progress}")
RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
mainHandler.removeCallbacks(updateTextTask)
underSeek = true
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
mainHandler.post(updateTextTask)
underSeek = false
hideTimer = 0
}
})
更新文本任务:
private val updateTextTask = object : Runnable {
override fun run() {
RLog.d("----------------------------")
RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
binding.progressBarVideo.progress = binding.videoViewF.currentPosition
mainHandler.postDelayed(this, 1000)
}
}
格式持续时间:
@SuppressLint("DefaultLocale")
private fun durationToFormat(duration: Int): String {
return java.lang.String.format(
"%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(duration.toLong()),
TimeUnit.MILLISECONDS.toSeconds(duration.toLong()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration.toLong()))
)
}
日志:
#onProgressChanged: ------------------
#onProgressChanged: Seekbar progress: 257875
#onProgressChanged: videoView position: 257875
#onProgressChanged: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 257875
#run: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 256957
#run: Time display string: 04:16
#run: ----------------------------
可以看到,seek后时间是257875,timer第一次迭代也是257875,然后跳到256957,不明白为什么...
我不确定,但我想问题出在 postDelayed,因为它实际上 运行 在 1 秒后。所以尝试在这里添加 1000 毫秒,希望它能正确运行。
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition + 1000)}")
您似乎从 runnable 再次更新进度,因此将从循环中调用 onProgressChanged 并将进度重置到之前的位置。
在这种情况下,您可以从代码中过滤掉进度更新,并且仅当 fromUser
为 true
时才在 onProgressChanged:
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
binding.videoViewF.seekTo(seekBar.progress)
}
binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
}
private val updateTextTask = object : Runnable {
override fun run() {
binding.progressBarVideo.progress = binding.videoViewF.currentPosition
mainHandler.postDelayed(this, 1000)
}
}
同样在这种情况下,您可以从 runnable 中删除文本更新,因为它将由 ProgressBar 位置更新触发。