mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-01-06 01:20:29 +05:30
Fix gesture controls for portrait videos
Use `PlayerViewModel.isFullscreen` to check if video is playing in full screen instead of screen orientation. Scale progress bar `progress` according to it's max size.
This commit is contained in:
parent
b3824b2e43
commit
fe02b0e30c
@ -9,6 +9,7 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
@ -16,6 +17,7 @@ import com.github.libretube.constants.IntentData
|
|||||||
import com.github.libretube.databinding.ActivityOfflinePlayerBinding
|
import com.github.libretube.databinding.ActivityOfflinePlayerBinding
|
||||||
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
||||||
import com.github.libretube.ui.base.BaseActivity
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
|
import com.github.libretube.ui.models.PlayerViewModel
|
||||||
import com.github.libretube.util.DownloadHelper
|
import com.github.libretube.util.DownloadHelper
|
||||||
import com.github.libretube.util.PlayerHelper
|
import com.github.libretube.util.PlayerHelper
|
||||||
import com.google.android.exoplayer2.ExoPlayer
|
import com.google.android.exoplayer2.ExoPlayer
|
||||||
@ -32,6 +34,7 @@ class OfflinePlayerActivity : BaseActivity() {
|
|||||||
private lateinit var player: ExoPlayer
|
private lateinit var player: ExoPlayer
|
||||||
private lateinit var playerView: StyledPlayerView
|
private lateinit var playerView: StyledPlayerView
|
||||||
private lateinit var playerBinding: ExoStyledPlayerControlViewBinding
|
private lateinit var playerBinding: ExoStyledPlayerControlViewBinding
|
||||||
|
private val playerViewModel: PlayerViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
hideSystemBars()
|
hideSystemBars()
|
||||||
@ -154,6 +157,16 @@ class OfflinePlayerActivity : BaseActivity() {
|
|||||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
playerViewModel.isFullscreen.value = true
|
||||||
|
super.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
playerViewModel.isFullscreen.value = false
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
player.release()
|
player.release()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
@ -19,4 +19,6 @@ interface PlayerGestureOptions {
|
|||||||
fun onZoom()
|
fun onZoom()
|
||||||
|
|
||||||
fun onMinimize()
|
fun onMinimize()
|
||||||
|
|
||||||
|
fun onFullscreenChange(isFullscreen: Boolean)
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,11 @@ internal class CustomExoPlayerView(
|
|||||||
this.doubleTapOverlayBinding = doubleTapOverlayBinding
|
this.doubleTapOverlayBinding = doubleTapOverlayBinding
|
||||||
this.trackSelector = trackSelector
|
this.trackSelector = trackSelector
|
||||||
this.gestureViewBinding = playerGestureControlsViewBinding
|
this.gestureViewBinding = playerGestureControlsViewBinding
|
||||||
this.playerGestureController = PlayerGestureController(context, this)
|
this.playerGestureController = PlayerGestureController(context as BaseActivity, this)
|
||||||
this.brightnessHelper = BrightnessHelper(context as Activity)
|
this.brightnessHelper = BrightnessHelper(context as Activity)
|
||||||
this.audioHelper = AudioHelper(context)
|
this.audioHelper = AudioHelper(context)
|
||||||
|
|
||||||
// Set touch listner for tap and swipe gestures.
|
// Set touch listener for tap and swipe gestures.
|
||||||
setOnTouchListener(playerGestureController)
|
setOnTouchListener(playerGestureController)
|
||||||
initializeGestureProgress()
|
initializeGestureProgress()
|
||||||
|
|
||||||
@ -461,13 +461,6 @@ internal class CustomExoPlayerView(
|
|||||||
params.bottomMargin = offset.toInt()
|
params.bottomMargin = offset.toInt()
|
||||||
it.layoutParams = params
|
it.layoutParams = params
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerHelper.swipeGestureEnabled && this::brightnessHelper.isInitialized) {
|
|
||||||
when (newConfig?.orientation) {
|
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> brightnessHelper.restoreSavedBrightness()
|
|
||||||
else -> brightnessHelper.resetToSystemBrightness(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSingleTap() {
|
override fun onSingleTap() {
|
||||||
@ -497,14 +490,14 @@ internal class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSwipeLeftScreen(distanceY: Float) {
|
override fun onSwipeLeftScreen(distanceY: Float) {
|
||||||
if (!PlayerHelper.swipeGestureEnabled || resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) return
|
if (!PlayerHelper.swipeGestureEnabled) return
|
||||||
|
|
||||||
if (isControllerFullyVisible) hideController()
|
if (isControllerFullyVisible) hideController()
|
||||||
updateBrightness(distanceY)
|
updateBrightness(distanceY)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSwipeRightScreen(distanceY: Float) {
|
override fun onSwipeRightScreen(distanceY: Float) {
|
||||||
if (!PlayerHelper.swipeGestureEnabled || resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) return
|
if (!PlayerHelper.swipeGestureEnabled) return
|
||||||
|
|
||||||
if (isControllerFullyVisible) hideController()
|
if (isControllerFullyVisible) hideController()
|
||||||
updateVolume(distanceY)
|
updateVolume(distanceY)
|
||||||
@ -522,4 +515,14 @@ internal class CustomExoPlayerView(
|
|||||||
override fun onMinimize() {
|
override fun onMinimize() {
|
||||||
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
|
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFullscreenChange(isFullscreen: Boolean) {
|
||||||
|
if (PlayerHelper.swipeGestureEnabled && this::brightnessHelper.isInitialized) {
|
||||||
|
if (isFullscreen) {
|
||||||
|
brightnessHelper.restoreSavedBrightness()
|
||||||
|
} else {
|
||||||
|
brightnessHelper.resetToSystemBrightness(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import android.util.AttributeSet
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import com.github.libretube.databinding.PlayerGestureControlsViewBinding
|
import com.github.libretube.databinding.PlayerGestureControlsViewBinding
|
||||||
|
import com.github.libretube.extensions.normalize
|
||||||
|
|
||||||
class PlayerGestureControlsView(
|
class PlayerGestureControlsView(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -20,7 +21,21 @@ class PlayerGestureControlsView(
|
|||||||
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
|
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
|
||||||
super.onSizeChanged(width, height, oldHeight, oldHeight)
|
super.onSizeChanged(width, height, oldHeight, oldHeight)
|
||||||
|
|
||||||
binding.brightnessProgressBar.max = (height * 0.7).toInt()
|
// Set new max value of progress bar corresponding to the new height and
|
||||||
binding.volumeProgressBar.max = (height * 0.7).toInt()
|
// make progress accordingly, store oldProgress before changing it to avoid
|
||||||
|
// inconsistency when old progress > new max
|
||||||
|
binding.brightnessProgressBar.apply {
|
||||||
|
val oldMax = max
|
||||||
|
val oldProgress = progress
|
||||||
|
max = (height * 0.7).toInt()
|
||||||
|
progress = oldProgress.normalize(0, oldMax, 0, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.volumeProgressBar.apply {
|
||||||
|
val oldMax = max
|
||||||
|
val oldProgress = progress
|
||||||
|
max = (height * 0.7).toInt()
|
||||||
|
progress = oldProgress.normalize(0, oldMax, 0, max)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.github.libretube.util
|
package com.github.libretube.util
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.os.Build
|
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.extensions.normalize
|
import com.github.libretube.extensions.normalize
|
||||||
@ -46,9 +45,6 @@ class BrightnessHelper(private val activity: Activity) {
|
|||||||
* Set current screen brightness to saved brightness value.
|
* Set current screen brightness to saved brightness value.
|
||||||
*/
|
*/
|
||||||
fun restoreSavedBrightness() {
|
fun restoreSavedBrightness() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && activity.isInPictureInPictureMode) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
brightness = savedBrightness
|
brightness = savedBrightness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.libretube.util
|
package com.github.libretube.util
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
@ -11,27 +9,36 @@ import android.view.GestureDetector
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.ScaleGestureDetector
|
import android.view.ScaleGestureDetector
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
||||||
|
import com.github.libretube.ui.models.PlayerViewModel
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
class PlayerGestureController(context: Context, private val listener: PlayerGestureOptions) :
|
class PlayerGestureController(activity: BaseActivity, private val listener: PlayerGestureOptions) :
|
||||||
View.OnTouchListener {
|
View.OnTouchListener {
|
||||||
|
|
||||||
// width and height should be obtained each time using getter to adopt layout size changes.
|
// width and height should be obtained each time using getter to adopt layout size changes.
|
||||||
private val width get() = Resources.getSystem().displayMetrics.widthPixels
|
private val width get() = Resources.getSystem().displayMetrics.widthPixels
|
||||||
private val height get() = Resources.getSystem().displayMetrics.heightPixels
|
private val height get() = Resources.getSystem().displayMetrics.heightPixels
|
||||||
private val orientation get() = Resources.getSystem().configuration.orientation
|
|
||||||
private val elapsedTime get() = SystemClock.elapsedRealtime()
|
private val elapsedTime get() = SystemClock.elapsedRealtime()
|
||||||
|
private val playerViewModel: PlayerViewModel by activity.viewModels()
|
||||||
|
|
||||||
private val handler: Handler = Handler(Looper.getMainLooper())
|
private val handler: Handler = Handler(Looper.getMainLooper())
|
||||||
private val gestureDetector: GestureDetector
|
private val gestureDetector: GestureDetector
|
||||||
private val scaleGestureDetector: ScaleGestureDetector
|
private val scaleGestureDetector: ScaleGestureDetector
|
||||||
|
private var isFullscreen = false
|
||||||
private var isMoving = false
|
private var isMoving = false
|
||||||
var isEnabled = true
|
var isEnabled = true
|
||||||
|
|
||||||
init {
|
init {
|
||||||
gestureDetector = GestureDetector(context, GestureListener(), handler)
|
gestureDetector = GestureDetector(activity, GestureListener(), handler)
|
||||||
scaleGestureDetector = ScaleGestureDetector(context, ScaleGestureListener(), handler)
|
scaleGestureDetector = ScaleGestureDetector(activity, ScaleGestureListener(), handler)
|
||||||
|
|
||||||
|
playerViewModel.isFullscreen.observe(activity) {
|
||||||
|
isFullscreen = it
|
||||||
|
listener.onFullscreenChange(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@ -47,8 +54,8 @@ class PlayerGestureController(context: Context, private val listener: PlayerGest
|
|||||||
gestureDetector.onTouchEvent(event)
|
gestureDetector.onTouchEvent(event)
|
||||||
} catch (_: Exception) { }
|
} catch (_: Exception) { }
|
||||||
|
|
||||||
// If orientation is landscape then allow `onScroll` to consume event and return true.
|
// If video is playing in full-screen then allow `onScroll` to consume event and return true.
|
||||||
return orientation == Configuration.ORIENTATION_LANDSCAPE
|
return isFullscreen
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ScaleGestureListener : ScaleGestureDetector.OnScaleGestureListener {
|
private inner class ScaleGestureListener : ScaleGestureDetector.OnScaleGestureListener {
|
||||||
|
Loading…
Reference in New Issue
Block a user