Allow seeking video by swiping or tapping (#132)

* Allow seeking in players by tapping

* Allow seeking in players by swiping horizontally

* Small cleanup

Co-authored-by: Jarne Demeulemeester <jarnedemeulemeester@gmail.com>
This commit is contained in:
Yusuf 2022-07-29 19:48:47 +03:00 committed by GitHub
parent 4a7f039664
commit 53d1720ad0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 112 additions and 9 deletions

View file

@ -34,32 +34,81 @@ class PlayerGestureHelper(
private var swipeGestureValueTrackerVolume = -1f
private var swipeGestureValueTrackerBrightness = -1f
private var swipeGestureValueTrackerProgress = -1L
private var swipeGestureVolumeOpen = false
private var swipeGestureBrightnessOpen = false
private var swipeGestureProgressOpen = false
private val tapGestureDetector = GestureDetector(playerView.context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent?): Boolean {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
playerView.apply {
if (!isControllerFullyVisible) showController() else hideController()
}
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
val viewCenterX = playerView.measuredWidth / 2
val currentPos = playerView.player?.currentPosition ?: 0
if (e.x.toInt() > viewCenterX) {
playerView.player?.seekTo(currentPos + appPreferences.playerSeekForwardIncrement)
}
else {
playerView.player?.seekTo((currentPos - appPreferences.playerSeekBackIncrement).coerceAtLeast(0))
}
return true
}
})
private val gestureDetector = GestureDetector(playerView.context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
playerView.apply {
if (!isControllerFullyVisible) showController() else hideController()
}
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
val viewCenterX = playerView.measuredWidth / 2
val currentPos = playerView.player?.currentPosition ?: 0
if (e.x.toInt() > viewCenterX) {
playerView.player?.seekTo(currentPos + appPreferences.playerSeekForwardIncrement)
}
else {
playerView.player?.seekTo((currentPos - appPreferences.playerSeekBackIncrement).coerceAtLeast(0))
}
return true
}
override fun onScroll(firstEvent: MotionEvent, currentEvent: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
// Check whether swipe was oriented vertically
if (abs(distanceY / distanceX) < 2)
return false
if (firstEvent.y < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_TOP))
return false
// Check whether swipe was oriented vertically
if (abs(distanceY / distanceX) < 2) {
return if ((abs(currentEvent.x - firstEvent.x) > 50 || swipeGestureProgressOpen) &&
(!swipeGestureBrightnessOpen && !swipeGestureVolumeOpen)) {
val currentPos = playerView.player?.currentPosition ?: 0
val vidDuration = playerView.player?.duration ?: 0
val difference = ((currentEvent.x - firstEvent.x) * 90).toLong()
val newPos = (currentPos + difference).coerceIn(0, vidDuration)
activity.binding.progressScrubberLayout.visibility = View.VISIBLE
activity.binding.progressScrubberText.text = "${longToTimestamp(difference)} [${longToTimestamp(newPos, true)}]"
swipeGestureValueTrackerProgress = newPos
swipeGestureProgressOpen = true
true
} else false
}
if (swipeGestureValueTrackerProgress > -1 || swipeGestureProgressOpen)
return false
val viewCenterX = playerView.measuredWidth / 2
@ -84,6 +133,8 @@ class PlayerGestureHelper(
activity.binding.gestureVolumeProgressBar.max = maxVolume
activity.binding.gestureVolumeProgressBar.progress = toSet
activity.binding.gestureVolumeText.text = "${(toSet.toFloat()/maxVolume.toFloat()).times(100).toInt()}%"
swipeGestureVolumeOpen = true
} else {
// Swiping on the left, change brightness
val window = activity.window
@ -107,6 +158,8 @@ class PlayerGestureHelper(
activity.binding.gestureBrightnessProgressBar.max = BRIGHTNESS_OVERRIDE_FULL.times(100).toInt()
activity.binding.gestureBrightnessProgressBar.progress = lp.screenBrightness.times(100).toInt()
activity.binding.gestureBrightnessText.text = "${(lp.screenBrightness/BRIGHTNESS_OVERRIDE_FULL).times(100).toInt()}%"
swipeGestureBrightnessOpen = true
}
return true
}
@ -123,6 +176,10 @@ class PlayerGestureHelper(
}
}
private val hideGestureProgressOverlayAction = Runnable {
activity.binding.progressScrubberLayout.visibility = View.GONE
}
/**
* Handles scale/zoom gesture
*/
@ -151,17 +208,38 @@ class PlayerGestureHelper(
if (visibility == View.VISIBLE) {
removeCallbacks(hideGestureVolumeIndicatorOverlayAction)
postDelayed(hideGestureVolumeIndicatorOverlayAction, 1000)
swipeGestureVolumeOpen = false
}
}
activity.binding.gestureBrightnessLayout.apply {
if (visibility == View.VISIBLE) {
removeCallbacks(hideGestureBrightnessIndicatorOverlayAction)
postDelayed(hideGestureBrightnessIndicatorOverlayAction, 1000)
swipeGestureBrightnessOpen = false
}
}
activity.binding.progressScrubberLayout.apply {
if (visibility == View.VISIBLE) {
if (swipeGestureValueTrackerProgress > -1) {
playerView.player?.seekTo(swipeGestureValueTrackerProgress)
}
removeCallbacks(hideGestureProgressOverlayAction)
postDelayed(hideGestureProgressOverlayAction, 1000)
swipeGestureProgressOpen = false
swipeGestureValueTrackerProgress = -1L
}
}
}
}
private fun longToTimestamp(duration: Long, noSign: Boolean = false): String {
val sign = if (noSign) "" else if (duration < 0) "-" else "+"
val seconds = abs(duration).div(1000)
return String.format("%s%02d:%02d:%02d", sign, seconds / 3600, (seconds / 60) % 60, seconds % 60)
}
init {
if (appPreferences.playerBrightnessRemember) {
activity.window.attributes.screenBrightness = appPreferences.playerBrightness

View file

@ -12,7 +12,30 @@
android:layout_height="match_parent"
android:background="@color/black"
app:animation_enabled="false"
app:show_buffering="always" />
app:show_buffering="always">
</com.google.android.exoplayer2.ui.StyledPlayerView>
<LinearLayout
android:id="@+id/progress_scrubber_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/overlay_background"
android:clickable="false"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/progress_scrubber_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
android:textColor="@color/white"
tools:text="+00:00:10 [00:00:20]" />
</LinearLayout>
<LinearLayout
android:id="@+id/gesture_volume_layout"
@ -33,7 +56,8 @@
android:layout_height="24dp"
android:layout_marginVertical="16dp"
android:gravity="center"
android:textColor="@color/white" />
android:textColor="@color/white"
tools:text="58%" />
<ProgressBar
android:id="@+id/gesture_volume_progress_bar"
@ -71,7 +95,8 @@
android:layout_height="24dp"
android:layout_marginVertical="16dp"
android:gravity="center"
android:textColor="@color/white" />
android:textColor="@color/white"
tools:text="58%" />
<ProgressBar
android:id="@+id/gesture_brightness_progress_bar"