add rwd/ffwd double tap indicator & pause/play on long press
This commit is contained in:
parent
3880b3ab75
commit
256c32aa3c
|
@ -11,7 +11,6 @@ import android.view.*
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.postDelayed
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.Player
|
||||
|
@ -23,7 +22,10 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
|||
import com.google.android.exoplayer2.util.Util
|
||||
import kotlinx.android.synthetic.main.activity_player.*
|
||||
import kotlinx.android.synthetic.main.player_controls.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.preferences.Preferences
|
||||
import org.mosad.teapod.ui.fragments.MediaFragment
|
||||
|
@ -34,7 +36,6 @@ import java.util.*
|
|||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.concurrent.scheduleAtFixedRate
|
||||
|
||||
|
||||
class PlayerActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var player: SimpleExoPlayer
|
||||
|
@ -257,12 +258,52 @@ class PlayerActivity : AppCompatActivity() {
|
|||
Log.d(javaClass.name, "Released player")
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO set position of rewind/fast forward indicators programmatically
|
||||
*/
|
||||
|
||||
private fun rewind() {
|
||||
player.seekTo(player.currentPosition - rwdTime)
|
||||
|
||||
// hide/show needed components
|
||||
exo_double_tap_indicator.visibility = View.VISIBLE
|
||||
ffwd_10_indicator.visibility = View.INVISIBLE
|
||||
ffwd_10.visibility = View.INVISIBLE
|
||||
|
||||
rwd_10_indicator.onAnimationEndCallback = {
|
||||
exo_double_tap_indicator.visibility = View.GONE
|
||||
ffwd_10_indicator.visibility = View.VISIBLE
|
||||
ffwd_10.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
// run animation
|
||||
rwd_10_indicator.runOnClickAnimation()
|
||||
}
|
||||
|
||||
private fun forward() {
|
||||
player.seekTo(player.currentPosition + fwdTime)
|
||||
|
||||
// hide/show needed components
|
||||
exo_double_tap_indicator.visibility = View.VISIBLE
|
||||
rwd_10_indicator.visibility = View.INVISIBLE
|
||||
ffwd_10.visibility = View.INVISIBLE
|
||||
|
||||
ffwd_10_indicator.onAnimationEndCallback = {
|
||||
exo_double_tap_indicator.visibility = View.GONE
|
||||
rwd_10_indicator.visibility = View.VISIBLE
|
||||
ffwd_10.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
// run animation
|
||||
ffwd_10_indicator.runOnClickAnimation()
|
||||
}
|
||||
|
||||
private fun togglePausePlay() {
|
||||
if (player.isPlaying) {
|
||||
player.pause()
|
||||
} else {
|
||||
player.play()
|
||||
}
|
||||
}
|
||||
|
||||
private fun playNextEpisode() {
|
||||
|
@ -282,7 +323,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
// watchedCallback for next ep
|
||||
currentEpisode = nextEp // set current ep to next ep
|
||||
episodeId = nextEp.id
|
||||
MediaFragment.instance.updateWatchedState(nextEp) // TODO i don't like this
|
||||
MediaFragment.instance.updateWatchedState(nextEp)
|
||||
|
||||
nextEpisode = selectNextEpisode()
|
||||
}
|
||||
|
@ -362,15 +403,14 @@ class PlayerActivity : AppCompatActivity() {
|
|||
button_next_ep.animate()
|
||||
.alpha(0.0f)
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
super.onAnimationEnd(animation)
|
||||
button_next_ep.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
super.onAnimationEnd(animation)
|
||||
button_next_ep.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
inner class PlayerGestureListener : GestureDetector.SimpleOnGestureListener() {
|
||||
|
||||
/**
|
||||
|
@ -386,22 +426,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
*/
|
||||
override fun onDoubleTap(e: MotionEvent?): Boolean {
|
||||
val eventPosX = e?.x?.toInt() ?: 0
|
||||
val eventPosY = e?.y?.toInt() ?: 0
|
||||
val viewCenterX = video_view.measuredWidth / 2
|
||||
val viewCenterY = video_view.measuredHeight / 2
|
||||
|
||||
// Show ripple effect (Jellyfin Android App) TODO replace this with a netflix player like animation?
|
||||
video_view.foreground?.apply {
|
||||
val left = if (eventPosX < viewCenterX) 0 else viewCenterX
|
||||
val right = if (eventPosX < viewCenterX) viewCenterX else video_view.measuredWidth
|
||||
|
||||
setBounds(left, viewCenterY - viewCenterX / 2, right, viewCenterY + viewCenterX / 2)
|
||||
setHotspot(eventPosX.toFloat(), eventPosY.toFloat())
|
||||
state = intArrayOf(android.R.attr.state_enabled, android.R.attr.state_pressed)
|
||||
video_view.postDelayed(100) {
|
||||
state = IntArray(0)
|
||||
}
|
||||
}
|
||||
|
||||
// if the event position is on the left side rewind, if it's on the right forward
|
||||
if (eventPosX < viewCenterX) {
|
||||
|
@ -420,6 +445,10 @@ class PlayerActivity : AppCompatActivity() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun onLongPress(e: MotionEvent?) {
|
||||
togglePausePlay()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,24 +10,18 @@ import android.widget.FrameLayout
|
|||
import kotlinx.android.synthetic.main.button_fast_forward.view.*
|
||||
import org.mosad.teapod.R
|
||||
|
||||
class FastForwardButton(context: Context, attrs: AttributeSet): FrameLayout(context, attrs) {
|
||||
class FastForwardButton(context: Context, attrs: AttributeSet?): FrameLayout(context, attrs) {
|
||||
|
||||
private val animationDuration: Long = 800
|
||||
private val buttonAnimation: ObjectAnimator
|
||||
private val labelAnimation: ObjectAnimator
|
||||
|
||||
var onAnimationEndCallback: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.button_fast_forward, this)
|
||||
}
|
||||
|
||||
fun setOnButtonClickListener(func: FastForwardButton.() -> Unit) {
|
||||
imageButton.setOnClickListener {
|
||||
func()
|
||||
runOnClickAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnClickAnimation() {
|
||||
// run button animation
|
||||
ObjectAnimator.ofFloat(imageButton, View.ROTATION, 0f, 50f).apply {
|
||||
buttonAnimation = ObjectAnimator.ofFloat(imageButton, View.ROTATION, 0f, 50f).apply {
|
||||
duration = animationDuration / 4
|
||||
repeatCount = 1
|
||||
repeatMode = ObjectAnimator.REVERSE
|
||||
|
@ -36,29 +30,39 @@ class FastForwardButton(context: Context, attrs: AttributeSet): FrameLayout(cont
|
|||
imageButton.isEnabled = false // disable button
|
||||
imageButton.setBackgroundResource(R.drawable.ic_baseline_forward_24)
|
||||
}
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
imageButton.isEnabled = true // enable button
|
||||
}
|
||||
})
|
||||
start()
|
||||
}
|
||||
|
||||
// run lbl animation
|
||||
textView.visibility = View.VISIBLE
|
||||
ObjectAnimator.ofFloat(textView, View.TRANSLATION_X, 35f).apply {
|
||||
labelAnimation = ObjectAnimator.ofFloat(textView, View.TRANSLATION_X, 35f).apply {
|
||||
duration = animationDuration
|
||||
addListener(object : AnimatorListenerAdapter() {
|
||||
// the label animation takes longer then the button animation, reset stuff in here
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
imageButton.isEnabled = true // enable button
|
||||
imageButton.setBackgroundResource(R.drawable.ic_baseline_forward_10_24)
|
||||
|
||||
textView.visibility = View.GONE
|
||||
textView.animate().translationX(0f)
|
||||
|
||||
onAnimationEndCallback?.invoke()
|
||||
}
|
||||
})
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnButtonClickListener(func: FastForwardButton.() -> Unit) {
|
||||
imageButton.setOnClickListener {
|
||||
func()
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnClickAnimation() {
|
||||
// run button animation
|
||||
buttonAnimation.start()
|
||||
|
||||
// run lbl animation
|
||||
textView.visibility = View.VISIBLE
|
||||
labelAnimation.start()
|
||||
}
|
||||
|
||||
}
|
|
@ -13,21 +13,15 @@ import org.mosad.teapod.R
|
|||
class RewindButton(context: Context, attrs: AttributeSet): FrameLayout(context, attrs) {
|
||||
|
||||
private val animationDuration: Long = 800
|
||||
private val buttonAnimation: ObjectAnimator
|
||||
private val labelAnimation: ObjectAnimator
|
||||
|
||||
var onAnimationEndCallback: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.button_rewind, this)
|
||||
}
|
||||
|
||||
fun setOnButtonClickListener(func: RewindButton.() -> Unit) {
|
||||
imageButton.setOnClickListener {
|
||||
func()
|
||||
runOnClickAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnClickAnimation() {
|
||||
// run button animation
|
||||
ObjectAnimator.ofFloat(imageButton, View.ROTATION, 0f, -50f).apply {
|
||||
buttonAnimation = ObjectAnimator.ofFloat(imageButton, View.ROTATION, 0f, -50f).apply {
|
||||
duration = animationDuration / 4
|
||||
repeatCount = 1
|
||||
repeatMode = ObjectAnimator.REVERSE
|
||||
|
@ -36,16 +30,10 @@ class RewindButton(context: Context, attrs: AttributeSet): FrameLayout(context,
|
|||
imageButton.isEnabled = false // disable button
|
||||
imageButton.setBackgroundResource(R.drawable.ic_baseline_rewind_24)
|
||||
}
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
imageButton.isEnabled = true // enable button
|
||||
}
|
||||
})
|
||||
start()
|
||||
}
|
||||
|
||||
// run lbl animation
|
||||
textView.visibility = View.VISIBLE
|
||||
ObjectAnimator.ofFloat(textView, View.TRANSLATION_X, -35f).apply {
|
||||
labelAnimation = ObjectAnimator.ofFloat(textView, View.TRANSLATION_X, -35f).apply {
|
||||
duration = animationDuration
|
||||
addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
|
@ -54,11 +42,26 @@ class RewindButton(context: Context, attrs: AttributeSet): FrameLayout(context,
|
|||
|
||||
textView.visibility = View.GONE
|
||||
textView.animate().translationX(0f)
|
||||
|
||||
onAnimationEndCallback?.invoke()
|
||||
}
|
||||
})
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnButtonClickListener(func: RewindButton.() -> Unit) {
|
||||
imageButton.setOnClickListener {
|
||||
func()
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnClickAnimation() {
|
||||
// run button animation
|
||||
buttonAnimation.start()
|
||||
|
||||
// run lbl animation
|
||||
textView.visibility = View.VISIBLE
|
||||
labelAnimation.start()
|
||||
}
|
||||
|
||||
}
|
|
@ -2,10 +2,11 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/player_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
android:background="#000000"
|
||||
android:keepScreenOn="true"
|
||||
tools:context=".PlayerActivity">
|
||||
|
||||
<com.google.android.exoplayer2.ui.StyledPlayerView
|
||||
|
@ -15,9 +16,9 @@
|
|||
android:layout_gravity="center"
|
||||
android:animateLayoutChanges="true"
|
||||
android:foreground="@drawable/ripple_background"
|
||||
app:controller_layout_id="@layout/player_controls"
|
||||
app:fastforward_increment="10000"
|
||||
app:rewind_increment="10000"
|
||||
app:controller_layout_id="@layout/player_controls"/>
|
||||
app:rewind_increment="10000" />
|
||||
|
||||
<com.google.android.material.progressindicator.ProgressIndicator
|
||||
android:id="@+id/loading"
|
||||
|
@ -28,6 +29,50 @@
|
|||
app:indicatorColor="@color/exo_white"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/exo_double_tap_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<org.mosad.teapod.ui.components.RewindButton
|
||||
android:id="@+id/rwd_10_indicator"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Space
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="1dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<org.mosad.teapod.ui.components.FastForwardButton
|
||||
android:id="@+id/ffwd_10_indicator"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_next_ep"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
Loading…
Reference in New Issue