From fd099e97e688311fb3fa65befe52504163e421ac Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 15 Nov 2020 17:17:56 +0100 Subject: [PATCH] add visual indicator for rewind/forward gesture --- .../java/org/mosad/teapod/PlayerActivity.kt | 65 +++++++++++++------ .../main/res/drawable/ripple_background.xml | 3 + app/src/main/res/layout/activity_player.xml | 1 + app/src/main/res/layout/player_controls.xml | 3 +- 4 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 app/src/main/res/drawable/ripple_background.xml diff --git a/app/src/main/java/org/mosad/teapod/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/PlayerActivity.kt index 1f17bdb..fbd6aae 100644 --- a/app/src/main/java/org/mosad/teapod/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/PlayerActivity.kt @@ -11,6 +11,7 @@ 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 @@ -28,7 +29,9 @@ import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.util.DataTypes.MediaType import org.mosad.teapod.util.Episode import org.mosad.teapod.util.Media +import java.util.* import java.util.concurrent.TimeUnit +import kotlin.concurrent.scheduleAtFixedRate class PlayerActivity : AppCompatActivity() { @@ -37,6 +40,7 @@ class PlayerActivity : AppCompatActivity() { private lateinit var dataSourceFactory: DataSource.Factory private lateinit var controller: StyledPlayerControlView private lateinit var gestureDetector: GestureDetectorCompat + private lateinit var timerUpdates: TimerTask private var mediaId = 0 private var episodeId = 0 @@ -213,28 +217,32 @@ class PlayerActivity : AppCompatActivity() { button_next_ep.setOnClickListener { playNextEpisode() } } - private fun initTimeUpdates() = GlobalScope.launch { - while (true) { - val remainingTime = withContext(Dispatchers.Main) { - player.duration - player.currentPosition - } + private fun initTimeUpdates() { + if (this::timerUpdates.isInitialized) { + timerUpdates.cancel() + } + + timerUpdates = Timer().scheduleAtFixedRate(0, 1000) { + GlobalScope.launch { + var btnNextEpIsVisible: Boolean + var remainingTime: Long - if (remainingTime in 0..20000) { withContext(Dispatchers.Main) { - // if the next ep button is not visible, make it visible - if (!button_next_ep.isVisible && nextEpisode != null && Preferences.autoplay) { - showButtonNextEp() - } + btnNextEpIsVisible = button_next_ep.isVisible + remainingTime = player.duration - player.currentPosition } - } else { - withContext(Dispatchers.Main) { - if (button_next_ep.isVisible) { - hideButtonNextEp() + + if (remainingTime in 0..20000) { + if (!btnNextEpIsVisible && nextEpisode != null && Preferences.autoplay) { + // if the next ep button is not visible, make it visible + withContext(Dispatchers.Main) { showButtonNextEp() } + } + } else { + if (btnNextEpIsVisible) { + withContext(Dispatchers.Main) { hideButtonNextEp() } } } } - - delay(1000) } } @@ -243,6 +251,7 @@ class PlayerActivity : AppCompatActivity() { currentWindow = player.currentWindowIndex playWhenReady = player.playWhenReady player.release() + timerUpdates.cancel() Log.d(javaClass.name, "Released player") } @@ -338,6 +347,8 @@ class PlayerActivity : AppCompatActivity() { .setListener(null) } + + /** * hide the next episode button * TODO improve the hide animation @@ -369,12 +380,26 @@ class PlayerActivity : AppCompatActivity() { * on double tap rewind or forward */ override fun onDoubleTap(e: MotionEvent?): Boolean { - val eventPos = e?.x?.toInt() ?: 0 - val viewCenter = video_view.measuredWidth / 2 + 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) + } + } - // TODO show indicator for tap action // if the event position is on the left side rewind, if it's on the right forward - if (eventPos < viewCenter) { + if (eventPosX < viewCenterX) { rewind() } else { forward() diff --git a/app/src/main/res/drawable/ripple_background.xml b/app/src/main/res/drawable/ripple_background.xml new file mode 100644 index 0000000..86cd55e --- /dev/null +++ b/app/src/main/res/drawable/ripple_background.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_player.xml b/app/src/main/res/layout/activity_player.xml index c814052..a8be9bf 100644 --- a/app/src/main/res/layout/activity_player.xml +++ b/app/src/main/res/layout/activity_player.xml @@ -14,6 +14,7 @@ android:layout_height="match_parent" android:layout_gravity="center" android:animateLayoutChanges="true" + android:foreground="@drawable/ripple_background" app:fastforward_increment="10000" app:rewind_increment="10000" app:controller_layout_id="@layout/player_controls"/> diff --git a/app/src/main/res/layout/player_controls.xml b/app/src/main/res/layout/player_controls.xml index 9bb05da..832ae97 100644 --- a/app/src/main/res/layout/player_controls.xml +++ b/app/src/main/res/layout/player_controls.xml @@ -31,7 +31,8 @@ android:layout_marginEnd="44dp" android:text="@string/text_title_ex" android:textAlignment="center" - android:textColor="@color/exo_white" /> + android:textColor="@color/exo_white" + android:textSize="16sp" />