From ce66873ef333327b5a63b0ea36f559ed1dce5f5f Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 26 Nov 2022 11:10:18 +0100 Subject: [PATCH 1/2] pinch to zoom --- .../ui/interfaces/PlayerGestureOptions.kt | 4 +++ .../libretube/ui/views/CustomExoPlayerView.kt | 8 ++++++ .../libretube/util/PlayerGestureController.kt | 27 ++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/ui/interfaces/PlayerGestureOptions.kt b/app/src/main/java/com/github/libretube/ui/interfaces/PlayerGestureOptions.kt index ee6e60dd1..81602351a 100644 --- a/app/src/main/java/com/github/libretube/ui/interfaces/PlayerGestureOptions.kt +++ b/app/src/main/java/com/github/libretube/ui/interfaces/PlayerGestureOptions.kt @@ -15,4 +15,8 @@ interface PlayerGestureOptions { fun onSwipeRightScreen(distanceY: Float) fun onSwipeEnd() + + fun onZoom() + + fun onMinimize() } diff --git a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt index ccb198f29..9b4ece133 100644 --- a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt +++ b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt @@ -492,4 +492,12 @@ internal class CustomExoPlayerView( gestureViewBinding.brightnessControlView.visibility = View.GONE gestureViewBinding.volumeControlView.visibility = View.GONE } + + override fun onZoom() { + resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM + } + + override fun onMinimize() { + resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT + } } diff --git a/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt b/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt index d647306b8..a90caa195 100644 --- a/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt +++ b/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt @@ -9,6 +9,7 @@ import android.os.Looper import android.os.SystemClock import android.view.GestureDetector import android.view.MotionEvent +import android.view.ScaleGestureDetector import android.view.View import com.github.libretube.ui.interfaces.PlayerGestureOptions import kotlin.math.abs @@ -24,11 +25,13 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu private val handler: Handler = Handler(Looper.getMainLooper()) private val gestureDetector: GestureDetector + private val scaleGestureDetector: ScaleGestureDetector private var isMoving = false var isEnabled = true init { gestureDetector = GestureDetector(context, GestureListener(), handler) + scaleGestureDetector = ScaleGestureDetector(context, ScaleGestureListener(), handler) } @SuppressLint("ClickableViewAccessibility") @@ -40,13 +43,35 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu // Event can be already consumed by some view which may lead to NPE. try { - gestureDetector.onTouchEvent(event) + val consumed = gestureDetector.onTouchEvent(event) + if (!consumed) scaleGestureDetector.onTouchEvent(event) } catch (_: Exception) { } // If orientation is landscape then allow `onScroll` to consume event and return true. return orientation == Configuration.ORIENTATION_LANDSCAPE } + private inner class ScaleGestureListener : ScaleGestureDetector.OnScaleGestureListener { + var scaleFactor: Float = 1f + + override fun onScale(detector: ScaleGestureDetector): Boolean { + scaleFactor *= detector.scaleFactor + return true + } + + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + return true + } + + override fun onScaleEnd(detector: ScaleGestureDetector) { + when { + scaleFactor < 0.8 -> listner.onMinimize() + scaleFactor > 1.2 -> listner.onZoom() + } + scaleFactor = 1f + } + } + private inner class GestureListener : GestureDetector.SimpleOnGestureListener() { private var lastClick = 0L private var lastDoubleClick = 0L From 2ebebb4b42bb8e4a56b8c687cb89ae224690a283 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 26 Nov 2022 15:10:39 +0100 Subject: [PATCH 2/2] fix accidential volume/brightness changes when zooming --- .../libretube/util/PlayerGestureController.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt b/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt index a90caa195..13ee55791 100644 --- a/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt +++ b/app/src/main/java/com/github/libretube/util/PlayerGestureController.kt @@ -14,7 +14,7 @@ import android.view.View import com.github.libretube.ui.interfaces.PlayerGestureOptions import kotlin.math.abs -class PlayerGestureController(context: Context, private val listner: PlayerGestureOptions) : +class PlayerGestureController(context: Context, private val listener: PlayerGestureOptions) : View.OnTouchListener { // width and height should be obtained each time using getter to adopt layout size changes. @@ -38,13 +38,13 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu override fun onTouch(v: View, event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_UP && isMoving) { isMoving = false - listner.onSwipeEnd() + listener.onSwipeEnd() } // Event can be already consumed by some view which may lead to NPE. try { - val consumed = gestureDetector.onTouchEvent(event) - if (!consumed) scaleGestureDetector.onTouchEvent(event) + scaleGestureDetector.onTouchEvent(event) + gestureDetector.onTouchEvent(event) } catch (_: Exception) { } // If orientation is landscape then allow `onScroll` to consume event and return true. @@ -65,8 +65,8 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu override fun onScaleEnd(detector: ScaleGestureDetector) { when { - scaleFactor < 0.8 -> listner.onMinimize() - scaleFactor > 1.2 -> listner.onZoom() + scaleFactor < 0.8 -> listener.onMinimize() + scaleFactor > 1.2 -> listener.onZoom() } scaleFactor = 1f } @@ -78,7 +78,7 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu private var xPos = 0.0F override fun onDown(e: MotionEvent): Boolean { - if (isMoving) return false + if (isMoving || scaleGestureDetector.isInProgress) return false if (isEnabled && isSecondClick()) { handler.removeCallbacks(runnable) @@ -86,9 +86,9 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu val eventPositionPercentageX = xPos / width when { - eventPositionPercentageX < 0.4 -> listner.onDoubleTapLeftScreen() - eventPositionPercentageX > 0.6 -> listner.onDoubleTapRightScreen() - else -> listner.onDoubleTapCenterScreen() + eventPositionPercentageX < 0.4 -> listener.onDoubleTapLeftScreen() + eventPositionPercentageX > 0.6 -> listener.onDoubleTapRightScreen() + else -> listener.onDoubleTapCenterScreen() } } else { if (recentDoubleClick()) return true @@ -106,7 +106,7 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu distanceX: Float, distanceY: Float ): Boolean { - if (!isEnabled) return false + if (!isEnabled || scaleGestureDetector.isInProgress) return false val insideThreshHold = abs(e2.y - e1.y) <= MOVEMENT_THRESHOLD val insideBorder = (e1.x < BORDER_THRESHOLD || e1.y < BORDER_THRESHOLD || e1.x > width - BORDER_THRESHOLD || e1.y > height - BORDER_THRESHOLD) @@ -126,8 +126,8 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu isMoving = true when { - width * 0.5 > e1.x -> listner.onSwipeLeftScreen(distanceY) - width * 0.5 < e1.x -> listner.onSwipeRightScreen(distanceY) + width * 0.5 > e1.x -> listener.onSwipeLeftScreen(distanceY) + width * 0.5 < e1.x -> listener.onSwipeRightScreen(distanceY) } return true } @@ -135,7 +135,7 @@ class PlayerGestureController(context: Context, private val listner: PlayerGestu private val runnable = Runnable { // If user is scrolling then avoid single tap call if (isMoving || isSecondClick()) return@Runnable - listner.onSingleTap() + listener.onSingleTap() } private fun isSecondClick(): Boolean {