Minor mpv-player UI fixes (#517)

* Condense code + bug fixes

* Add double tap to play/pause

* Fix few button highlights

* prevent controls auto fade when paused

* fix max of negative brightness bar
This commit is contained in:
Quickdesh 2022-04-13 19:26:48 +09:00 committed by GitHub
parent 494b2bb374
commit c703e1fa86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 394 additions and 323 deletions

View file

@ -23,23 +23,9 @@ class Gestures(
return true
}
override fun onSingleTapUp(e: MotionEvent): Boolean {
if (e.y < height * 0.05F || e.y > height * 0.95F || e.x < width * 0.05F || e.x > width * 0.95F) return false
when {
e.x < width * 0.4F -> return false
e.x > width * 0.6F -> return false
else -> activity.toggleControls()
}
return true
}
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
if (e.y < height * 0.05F || e.y > height * 0.95F || e.x < width * 0.05F || e.x > width * 0.95F) return false
when {
e.x < width * 0.4F -> activity.toggleControls()
e.x > width * 0.6F -> activity.toggleControls()
else -> return false
}
activity.toggleControls()
return true
}
@ -50,20 +36,11 @@ class Gestures(
when {
e.x < width * 0.4F -> activity.doubleTapSeek(-interval, e)
e.x > width * 0.6F -> activity.doubleTapSeek(interval, e)
else -> activity.doubleTapPlayPause()
}
return true
}
override fun onDoubleTapEvent(e: MotionEvent): Boolean {
if (activity.isLocked) return false
if (e.y < height * 0.05F || e.y > height * 0.95F || e.x < width * 0.05F || e.x > width * 0.95F) return false
if (e.action == MotionEvent.ACTION_UP && e.x > width * 0.4F && e.x < width * 0.6F) {
activity.toggleControls()
return true
}
return false
}
override fun onScroll(
e1: MotionEvent,
e2: MotionEvent,

View file

@ -29,8 +29,8 @@ import android.view.View
import android.view.ViewAnimationUtils
import android.view.WindowManager
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.SeekBar
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
@ -198,9 +198,6 @@ class PlayerActivity :
private val animationHandler = Handler(Looper.getMainLooper())
// I spent like an hour trying to make the below 4 vals and functions, into one function. Failed miserably!
// All on you man, sorry
// Fade out seek text
private val seekTextRunnable = Runnable {
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
@ -209,13 +206,6 @@ class PlayerActivity :
}
}
private fun showSeekText() {
animationHandler.removeCallbacks(seekTextRunnable)
binding.seekView.visibility = View.VISIBLE
animationHandler.postDelayed(seekTextRunnable, 500L)
}
// Fade out Volume Bar
private val volumeViewRunnable = Runnable {
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
@ -224,13 +214,6 @@ class PlayerActivity :
}
}
private fun showVolumeView() {
animationHandler.removeCallbacks(volumeViewRunnable)
binding.volumeView.visibility = View.VISIBLE
animationHandler.postDelayed(volumeViewRunnable, 500L)
}
// Fade out Brightness Bar
private val brightnessViewRunnable = Runnable {
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
@ -239,26 +222,50 @@ class PlayerActivity :
}
}
private fun showBrightnessView() {
animationHandler.removeCallbacks(brightnessViewRunnable)
binding.brightnessView.visibility = View.VISIBLE
animationHandler.postDelayed(brightnessViewRunnable, 500L)
}
// Fade out Player controls
private val controlsViewRunnable = Runnable {
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
findViewById<RelativeLayout>(R.id.player_controls).startAnimation(fadeAnimation)
binding.playerControls.visibility = View.GONE
if (!isLocked) {
findViewById<LinearLayout>(R.id.controlsView).startAnimation(fadeAnimation)
binding.controlsView.visibility = View.GONE
} else {
findViewById<LinearLayout>(R.id.lockedView).startAnimation(fadeAnimation)
binding.lockedView.visibility = View.GONE
}
}
}
private fun showControlsView() {
animationHandler.removeCallbacks(controlsViewRunnable)
binding.playerControls.visibility = View.VISIBLE
private fun showGestureView(type: String) {
val callback: Runnable
val itemView: LinearLayout
val delay: Long
when (type) {
"seek" -> {
callback = seekTextRunnable
itemView = binding.seekView
delay = 500L
}
"volume" -> {
callback = volumeViewRunnable
itemView = binding.volumeView
delay = 500L
}
"brightness" -> {
callback = brightnessViewRunnable
itemView = binding.brightnessView
delay = 500L
}
"controls" -> {
callback = controlsViewRunnable
itemView = if (!isLocked) binding.controlsView else binding.lockedView
delay = 3500L
}
else -> return
}
animationHandler.postDelayed(controlsViewRunnable, 1500L)
animationHandler.removeCallbacks(callback)
itemView.visibility = View.VISIBLE
animationHandler.postDelayed(callback, delay)
}
private val seekBarChangeListener = object : SeekBar.OnSeekBarChangeListener {
@ -311,7 +318,10 @@ class PlayerActivity :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
window.navigationBarColor = 70000000
}
setVisibilities()
showGestureView("controls")
player.initialize(applicationContext.filesDir.path)
MPVLib.setOptionString("keep-open", "always")
player.addObserver(this)
@ -408,19 +418,36 @@ class PlayerActivity :
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
if (isLocked) {
// Hide controls
binding.playerControls.isVisible = false
binding.controlsView.isVisible = false
// Toggle unlock button
binding.unlockBtn.isVisible = !binding.unlockBtn.isVisible
if (!binding.lockedView.isVisible && !player.paused!!) showGestureView("controls")
else if (!binding.lockedView.isVisible && player.paused!!) binding.lockedView.visibility = View.VISIBLE
else {
animationHandler.removeCallbacks(controlsViewRunnable)
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
findViewById<LinearLayout>(R.id.lockedView).startAnimation(fadeAnimation)
binding.lockedView.visibility = View.GONE
}
}
} else {
if(!binding.playerControls.isVisible) showControlsView()
else { animationHandler.removeCallbacks(controlsViewRunnable); binding.playerControls.isVisible = false }
binding.unlockBtn.isVisible = false
if (!binding.controlsView.isVisible && !player.paused!!) showGestureView("controls")
else if (!binding.controlsView.isVisible && player.paused!!) binding.controlsView.visibility = View.VISIBLE
else {
animationHandler.removeCallbacks(controlsViewRunnable)
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
findViewById<LinearLayout>(R.id.controlsView).startAnimation(fadeAnimation)
binding.controlsView.visibility = View.GONE
}
}
binding.lockedView.isVisible = false
}
}
private fun hideControls(hide: Boolean) {
binding.playerControls.isVisible = !hide
binding.controlsView.isVisible = !hide
}
private fun showLoadingIndicator(visible: Boolean) {
@ -614,6 +641,37 @@ class PlayerActivity :
@Suppress("UNUSED_PARAMETER")
fun playPause(view: View) {
player.cyclePause()
when {
player.paused!! -> animationHandler.removeCallbacks(controlsViewRunnable)
binding.controlsView.isVisible -> showGestureView("controls")
}
}
val playPauseRunnable = Runnable {
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
findViewById<ImageView>(R.id.playPauseView).startAnimation(fadeAnimation)
binding.playPauseView.visibility = View.GONE
}
}
fun doubleTapPlayPause() {
animationHandler.removeCallbacks(playPauseRunnable)
playPause(binding.playBtn)
if (!binding.controlsView.isVisible) {
when {
player.paused!! -> { binding.playPauseView.setImageResource(R.drawable.ic_pause_80dp) }
!player.paused!! -> { binding.playPauseView.setImageResource(R.drawable.ic_play_arrow_80dp) }
}
// if (binding.controlsView.isVisible) { binding.playPauseView.visibility = View.GONE; binding.playPauseView.setBackgroundColor(0x00000000) } else { binding.playPauseView.visibility = View.VISIBLE; binding.playPauseView.setBackgroundColor(0x70000000) }
AnimationUtils.loadAnimation(this, R.anim.fade_in_medium).also { fadeAnimation ->
findViewById<ImageView>(R.id.playPauseView).startAnimation(fadeAnimation)
binding.playPauseView.visibility = View.VISIBLE
}
animationHandler.postDelayed(playPauseRunnable, 500L)
} else binding.playPauseView.visibility = View.GONE
}
fun doubleTapSeek(time: Int, event: MotionEvent? = null) {
@ -630,7 +688,7 @@ class PlayerActivity :
val diffText = Utils.prettyTime(time, true)
binding.seekText.text = getString(R.string.ui_seek_distance, Utils.prettyTime(newPos), diffText)
showSeekText()
showGestureView("seek")
}
fun verticalScrollLeft(diff: Float) {
@ -651,9 +709,8 @@ class PlayerActivity :
binding.brightnessText.text = finalBrightness.toString()
binding.brightnessBar.progress = finalBrightness
binding.brightnessBar.secondaryProgress = abs(finalBrightness)
if (finalBrightness >= 0) binding.brightnessImg.setImageResource(R.drawable.ic_brightness_positive_24dp)
else binding.brightnessImg.setImageResource(R.drawable.ic_brightness_negative_24dp)
showBrightnessView()
if (finalBrightness >= 0) { binding.brightnessImg.setImageResource(R.drawable.ic_brightness_positive_24dp); binding.brightnessBar.max = 100 } else { binding.brightnessImg.setImageResource(R.drawable.ic_brightness_negative_24dp); binding.brightnessBar.max = 75 }
showGestureView("brightness")
}
fun verticalScrollRight(diff: Float) {
@ -666,7 +723,7 @@ class PlayerActivity :
binding.volumeBar.progress = newVolume
if (newVolume == 0) binding.volumeImg.setImageResource(R.drawable.ic_volume_none_24dp)
else binding.volumeImg.setImageResource(R.drawable.ic_volume_high_24dp)
showVolumeView()
showGestureView("volume")
}
fun initSeek() {
@ -687,7 +744,7 @@ class PlayerActivity :
val diffText = Utils.prettyTime(newDiff, true)
binding.seekText.text = getString(R.string.ui_seek_distance, Utils.prettyTime(newPos), diffText)
showSeekText()
showGestureView("seek")
}
@Suppress("UNUSED_PARAMETER")

View file

@ -48,24 +48,38 @@
app:tint="?attr/colorAccent" />
</LinearLayout>
<LinearLayout
android:id="@+id/lockedView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:visibility="gone">
<ImageButton
android:id="@+id/unlockBtn"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="Unlock player"
android:src="@drawable/ic_lock_open_24dp"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:visibility="gone"
android:background="?attr/selectableItemBackgroundBorderless"
app:tint="?attr/colorOnPrimarySurface" />
<RelativeLayout
android:id="@+id/player_controls"
</LinearLayout>
<!-- Double layout for consistency in code -->
<LinearLayout
android:id="@+id/controlsView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#70000000">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="UselessParent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/controls_top"
android:layout_width="match_parent"
@ -76,6 +90,7 @@
android:id="@+id/backArrowBtn"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="Go back"
android:src="@drawable/ic_arrow_back_24dp"
android:layout_marginHorizontal="10dp"
android:background="?attr/selectableItemBackgroundBorderless"
@ -119,7 +134,8 @@
android:id="@+id/settingsBtn"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Settings"
android:background="?attr/selectableItemBackground"
android:onClick="openSettings"
android:layout_marginRight="10dp"
android:src="@drawable/ic_settings_24dp"
@ -132,9 +148,10 @@
android:id="@+id/cycleSubsBtn"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="Subtitles"
android:onClick="cycleSub"
android:src="@drawable/ic_subtitles_black_24dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
app:tint="?attr/colorOnPrimarySurface"
app:layout_constraintRight_toRightOf="@id/cycleAudioBtn"
app:layout_constraintRight_toLeftOf="@id/settingsBtn"
@ -144,7 +161,8 @@
android:id="@+id/cycleAudioBtn"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Audio"
android:background="?attr/selectableItemBackground"
android:onClick="cycleAudio"
android:src="@drawable/ic_audiotrack_black_24dp"
app:layout_constraintTop_toTopOf="parent"
@ -157,7 +175,7 @@
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_toLeftOf="@id/cycleAudioBtn"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
android:onClick="switchDecoder"
android:text=".."
android:textColor="?attr/colorOnPrimarySurface"
@ -243,7 +261,8 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginLeft="10dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Lock player"
android:background="?attr/selectableItemBackground"
android:src="@drawable/ic_lock_24dp"
app:tint="?attr/colorOnPrimarySurface" />
@ -251,7 +270,7 @@
android:id="@+id/cycleSpeedBtn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
android:onClick="cycleSpeed"
android:text=".."
android:textColor="?attr/colorOnPrimarySurface" />
@ -268,7 +287,7 @@
android:id="@+id/controls_skip_intro_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
android:onClick="skipIntro"
android:text="@string/player_controls_skip_intro_text"
android:textColor="?attr/colorOnPrimarySurface" />
@ -277,7 +296,7 @@
android:id="@+id/cycleViewModeBtn"
android:layout_width="48dp"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
android:contentDescription="Cycle view modes"
android:onClick="cycleViewMode"
android:src="@drawable/ic_fullscreen_black_24dp"
@ -356,6 +375,7 @@
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/volumeView"
@ -393,7 +413,8 @@
android:layout_height="20dp"
android:src="@drawable/ic_volume_high_24dp"
app:tint="?attr/colorOnPrimarySurface"
android:layout_marginTop="5dp"/>
android:layout_marginTop="5dp"
tools:ignore="ContentDescription" />
</LinearLayout>
@ -432,7 +453,8 @@
android:layout_height="20dp"
android:layout_marginTop="5dp"
android:src="@drawable/ic_brightness_positive_24dp"
app:tint="?attr/colorOnPrimarySurface" />
app:tint="?attr/colorOnPrimarySurface"
tools:ignore="ContentDescription" />
</LinearLayout>
@ -459,6 +481,21 @@
</LinearLayout>
<ImageButton
android:id="@+id/playPauseView"
android:layout_width="80dp"
android:layout_height="80dp"
android:state_enabled="true"
android:state_pressed="true"
android:state_focused="true"
android:layout_centerInParent="true"
android:contentDescription="Play/Pause"
android:textColor="@android:color/white"
android:background="#70000000"
android:visibility="gone"
app:tint="?attr/colorOnPrimarySurface"
tools:src="@drawable/ic_play_arrow_80dp" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/loading_indicator"
android:layout_width="100dp"