mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-22 10:46:50 +00:00
Design and animation updates for Media Preview.
This commit is contained in:
@@ -1,13 +1,24 @@
|
||||
package org.thoughtcrime.securesms.mediapreview
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.Animator.AnimatorListener
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieProperty
|
||||
import com.airbnb.lottie.model.KeyPath
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
/**
|
||||
* The bottom bar for the media preview. This includes the standard seek bar as well as playback controls,
|
||||
@@ -23,6 +34,7 @@ class MediaPreviewPlayerControlView @JvmOverloads constructor(
|
||||
val recyclerView: RecyclerView = findViewById(R.id.media_preview_album_rail)
|
||||
private val durationBar: LinearLayout = findViewById(R.id.exo_duration_viewgroup)
|
||||
private val videoControls: LinearLayout = findViewById(R.id.exo_button_viewgroup)
|
||||
private val durationLabel: TextView = findViewById(R.id.exo_duration)
|
||||
private val shareButton: ImageButton = findViewById(R.id.exo_share)
|
||||
private val forwardButton: ImageButton = findViewById(R.id.exo_forward)
|
||||
|
||||
@@ -47,12 +59,65 @@ class MediaPreviewPlayerControlView @JvmOverloads constructor(
|
||||
showTimeoutMs = -1
|
||||
}
|
||||
|
||||
fun setVisibility(mediaMode: MediaMode) {
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun setMediaMode(mediaMode: MediaMode) {
|
||||
durationBar.visibility = if (mediaMode == MediaMode.VIDEO) VISIBLE else GONE
|
||||
videoControls.visibility = if (mediaMode == MediaMode.VIDEO) VISIBLE else INVISIBLE
|
||||
if (mediaMode == MediaMode.VIDEO) {
|
||||
setProgressUpdateListener { position, _ ->
|
||||
val finalPlayer = player ?: return@setProgressUpdateListener
|
||||
val remainingDuration = (finalPlayer.duration - position).toDuration(DurationUnit.MILLISECONDS)
|
||||
val minutes: Long = remainingDuration.inWholeMinutes
|
||||
val seconds: Long = remainingDuration.inWholeSeconds % 60
|
||||
durationLabel.text = "–${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}"
|
||||
}
|
||||
} else {
|
||||
setProgressUpdateListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
fun setShareButtonListener(listener: OnClickListener?) = shareButton.setOnClickListener(listener)
|
||||
|
||||
fun setForwardButtonListener(listener: OnClickListener?) = forwardButton.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
class LottieAnimatedButton @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : LottieAnimationView(context, attrs) {
|
||||
|
||||
init {
|
||||
addValueCallback(KeyPath("**"), LottieProperty.COLOR) { ContextCompat.getColor(context, R.color.signal_colorOnSurface) }
|
||||
}
|
||||
|
||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
||||
when (event?.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
speed = 1f
|
||||
playAnimation()
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (isAnimating) {
|
||||
addAnimatorListener(object : AnimatorListener {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
removeAllAnimatorListeners()
|
||||
playAnimationReverse()
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {}
|
||||
override fun onAnimationCancel(animation: Animator?) {}
|
||||
override fun onAnimationRepeat(animation: Animator?) {}
|
||||
})
|
||||
} else {
|
||||
playAnimationReverse()
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event)
|
||||
}
|
||||
|
||||
private fun playAnimationReverse() {
|
||||
speed = -1f
|
||||
playAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
|
||||
} else {
|
||||
MediaPreviewPlayerControlView.MediaMode.fromString(currentItem.contentType)
|
||||
}
|
||||
binding.mediaPreviewPlaybackControls.setVisibility(mediaType)
|
||||
binding.mediaPreviewPlaybackControls.setMediaMode(mediaType)
|
||||
|
||||
binding.toolbar.title = getTitleText(currentItem, currentState.showThread)
|
||||
binding.toolbar.subtitle = getSubTitleText(currentItem)
|
||||
|
||||
Reference in New Issue
Block a user