#android #kotlin #android-videoview
Вопрос:
Я реализовал videoView
с помощью пользовательской панели поиска. При изменении положения панели поиска видео воспроизводится правильно, но время отображается неправильно. Это происходит потому videoView
, что позиция по какой-то причине возвращается. Это происходит не всегда, но очень часто.
Изменение панели поиска:
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(
"d:d",
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: ----------------------------
Как вы можете видеть, после поиска время равно 257875, первая итерация таймера также равна 257875. Затем он перескакивает на 256957, и я не понимаю, почему…
Ответ №1:
Похоже, что вы снова обновляете прогресс из своего запускаемого, поэтому 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)
}
}
Также в этом случае вы можете удалить обновление текста из выполняемого, так как оно будет вызвано обновлением позиции на панели прогресса.
Ответ №2:
я не уверен, но я думаю, что проблема в том, что postDelayed, так как на самом деле он запускается через 1 секунду. Поэтому попробуйте добавить сюда 1000 мс, надеюсь, он будет вести себя правильно.
RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition 1000)}")