Display the time within the seekbar preview

This commit is contained in:
Bnyro 2023-03-22 11:40:46 +01:00
parent abadd23fb4
commit bae235dabf
3 changed files with 47 additions and 21 deletions

View File

@ -1516,7 +1516,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
playerBinding.exoProgress.addListener( playerBinding.exoProgress.addListener(
SeekbarPreviewListener( SeekbarPreviewListener(
streams.previewFrames, streams.previewFrames,
playerBinding.seekbarPreview, playerBinding,
streams.duration * 1000 streams.duration * 1000
) )
) )

View File

@ -1,21 +1,22 @@
package com.github.libretube.ui.listeners package com.github.libretube.ui.listeners
import android.graphics.Bitmap import android.graphics.Bitmap
import android.text.format.DateUtils
import android.view.View import android.view.View
import android.view.ViewGroup.MarginLayoutParams import android.view.ViewGroup.MarginLayoutParams
import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.math.MathUtils import androidx.core.math.MathUtils
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import coil.request.ImageRequest import coil.request.ImageRequest
import com.github.libretube.api.obj.PreviewFrames import com.github.libretube.api.obj.PreviewFrames
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
import com.github.libretube.helpers.ImageHelper import com.github.libretube.helpers.ImageHelper
import com.github.libretube.obj.PreviewFrame import com.github.libretube.obj.PreviewFrame
import com.google.android.exoplayer2.ui.TimeBar import com.google.android.exoplayer2.ui.TimeBar
class SeekbarPreviewListener( class SeekbarPreviewListener(
private val previewFrames: List<PreviewFrames>, private val previewFrames: List<PreviewFrames>,
private val previewIv: ImageView, private val playerBinding: ExoStyledPlayerControlViewBinding,
private val duration: Long private val duration: Long
) : TimeBar.OnScrubListener { ) : TimeBar.OnScrubListener {
private var moving = false private var moving = false
@ -32,6 +33,7 @@ class SeekbarPreviewListener(
override fun onScrubMove(timeBar: TimeBar, position: Long) { override fun onScrubMove(timeBar: TimeBar, position: Long) {
moving = true moving = true
playerBinding.seekbarPreviewPosition.text = DateUtils.formatElapsedTime(position / 1000)
processPreview(position) processPreview(position)
} }
@ -41,14 +43,14 @@ class SeekbarPreviewListener(
override fun onScrubStop(timeBar: TimeBar, position: Long, canceled: Boolean) { override fun onScrubStop(timeBar: TimeBar, position: Long, canceled: Boolean) {
moving = false moving = false
// animate the disappearance of the preview image // animate the disappearance of the preview image
previewIv.animate() playerBinding.seekbarPreview.animate()
.alpha(0f) .alpha(0f)
.translationYBy(30f) .translationYBy(30f)
.setDuration(200) .setDuration(200)
.withEndAction { .withEndAction {
previewIv.visibility = View.GONE playerBinding.seekbarPreview.visibility = View.GONE
previewIv.translationY = previewIv.translationY - 30f playerBinding.seekbarPreview.translationY -= 30f
previewIv.alpha = 1f playerBinding.seekbarPreview.alpha = 1f
} }
.start() .start()
} }
@ -62,13 +64,13 @@ class SeekbarPreviewListener(
// update the offset of the preview image view // update the offset of the preview image view
updatePreviewX(position) updatePreviewX(position)
val request = ImageRequest.Builder(previewIv.context) val request = ImageRequest.Builder(playerBinding.seekbarPreview.context)
.data(previewFrame.previewUrl) .data(previewFrame.previewUrl)
.target { .target {
if (!moving) return@target if (!moving) return@target
val frame = cutOutBitmap(it.toBitmap(), previewFrame) val frame = cutOutBitmap(it.toBitmap(), previewFrame)
previewIv.setImageBitmap(frame) playerBinding.seekbarPreviewImage.setImageBitmap(frame)
previewIv.visibility = View.VISIBLE playerBinding.seekbarPreview.visibility = View.VISIBLE
} }
.build() .build()
@ -116,13 +118,13 @@ class SeekbarPreviewListener(
* Update the offset of the preview image to fit the current scrubber position * Update the offset of the preview image to fit the current scrubber position
*/ */
private fun updatePreviewX(position: Long) { private fun updatePreviewX(position: Long) {
previewIv.updateLayoutParams<MarginLayoutParams> { playerBinding.seekbarPreview.updateLayoutParams<MarginLayoutParams> {
val parentWidth = (previewIv.parent as View).width val parentWidth = (playerBinding.seekbarPreview.parent as View).width
// calculate the center-offset of the preview image view // calculate the center-offset of the preview image view
val offset = parentWidth * (position.toFloat() / duration.toFloat()) - val offset = parentWidth * (position.toFloat() / duration.toFloat()) -
previewIv.width / 2 playerBinding.seekbarPreview.width / 2
// normalize the offset to keep a minimum distance at left and right // normalize the offset to keep a minimum distance at left and right
val maxPadding = parentWidth - MIN_PADDING - previewIv.width val maxPadding = parentWidth - MIN_PADDING - playerBinding.seekbarPreview.width
marginStart = MathUtils.clamp(offset.toInt(), MIN_PADDING, maxPadding) marginStart = MathUtils.clamp(offset.toInt(), MIN_PADDING, maxPadding)
} }
} }

View File

@ -201,16 +201,40 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.imageview.ShapeableImageView <LinearLayout
android:id="@+id/seekbar_preview" android:id="@+id/seekbar_preview"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="70dp" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:orientation="vertical"
android:scaleType="fitCenter" android:translationY="30dp"
android:translationY="27dp"
android:translationZ="1dp" android:translationZ="1dp"
android:visibility="gone" android:visibility="gone">
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Small" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/seekbar_preview_image"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Small" />
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:padding="5dp"
app:strokeWidth="0dp">
<TextView
android:id="@+id/seekbar_preview_position"
android:layout_width="wrap_content"
android:layout_marginHorizontal="5dp"
android:layout_height="wrap_content" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"