mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-29 09:39:03 +03:00
New player UI animations (#651)
* fix autoplay not starting from beginning of episode * Add player aniamtions * add a central integer value * fix a visual bug * fix an RTL/LTR bug
This commit is contained in:
parent
d8c2c17631
commit
48feecd1c6
14 changed files with 175 additions and 78 deletions
|
@ -210,18 +210,18 @@ class PlayerActivity :
|
|||
binding.seekView.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Fade out Volume Bar
|
||||
// Slide out Volume Bar
|
||||
internal val volumeViewRunnable = Runnable {
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
|
||||
if (!playerControls.shouldHideUiForSeek) playerControls.binding.volumeView.startAnimation(fadeAnimation)
|
||||
AnimationUtils.loadAnimation(this, R.anim.player_exit_left).also { slideAnimation ->
|
||||
if (!playerControls.shouldHideUiForSeek) playerControls.binding.volumeView.startAnimation(slideAnimation)
|
||||
playerControls.binding.volumeView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
// Fade out Brightness Bar
|
||||
// Slide out Brightness Bar
|
||||
internal val brightnessViewRunnable = Runnable {
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
|
||||
if (!playerControls.shouldHideUiForSeek) playerControls.binding.brightnessView.startAnimation(fadeAnimation)
|
||||
AnimationUtils.loadAnimation(this, R.anim.player_exit_right).also { slideAnimation ->
|
||||
if (!playerControls.shouldHideUiForSeek) playerControls.binding.brightnessView.startAnimation(slideAnimation)
|
||||
playerControls.binding.brightnessView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
@ -240,11 +240,13 @@ class PlayerActivity :
|
|||
callback = volumeViewRunnable
|
||||
itemView = playerControls.binding.volumeView
|
||||
delay = 750L
|
||||
if (!itemView.isVisible) itemView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.player_enter_left))
|
||||
}
|
||||
"brightness" -> {
|
||||
callback = brightnessViewRunnable
|
||||
itemView = playerControls.binding.brightnessView
|
||||
delay = 750L
|
||||
if (!itemView.isVisible) itemView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.player_enter_right))
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
|
@ -505,7 +507,7 @@ class PlayerActivity :
|
|||
|
||||
// Fade out Player information text
|
||||
private val playerInformationRunnable = Runnable {
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_out_short).also { fadeAnimation ->
|
||||
playerControls.binding.playerInformation.startAnimation(fadeAnimation)
|
||||
playerControls.binding.playerInformation.visibility = View.GONE
|
||||
}
|
||||
|
@ -640,7 +642,7 @@ class PlayerActivity :
|
|||
}
|
||||
|
||||
private val doubleTapPlayPauseRunnable = Runnable {
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_out_medium).also { fadeAnimation ->
|
||||
AnimationUtils.loadAnimation(this, R.anim.player_fade_out).also { fadeAnimation ->
|
||||
binding.playPauseView.startAnimation(fadeAnimation)
|
||||
binding.playPauseView.visibility = View.GONE
|
||||
}
|
||||
|
@ -656,7 +658,7 @@ class PlayerActivity :
|
|||
!player.paused!! -> { binding.playPauseView.setImageResource(R.drawable.ic_play_arrow_72dp) }
|
||||
}
|
||||
|
||||
AnimationUtils.loadAnimation(this, R.anim.fade_in_medium).also { fadeAnimation ->
|
||||
AnimationUtils.loadAnimation(this, R.anim.player_fade_in).also { fadeAnimation ->
|
||||
binding.playPauseView.startAnimation(fadeAnimation)
|
||||
binding.playPauseView.visibility = View.VISIBLE
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class PlayerControlsView @JvmOverloads constructor(context: Context, attrs: Attr
|
|||
shouldHideUiForSeek = false
|
||||
activity.player.paused = wasPausedBeforeSeeking
|
||||
if (showControls) {
|
||||
AnimationUtils.loadAnimation(activity, R.anim.fade_in_medium).also { fadeAnimation ->
|
||||
AnimationUtils.loadAnimation(activity, R.anim.player_fade_in).also { fadeAnimation ->
|
||||
binding.topControlsGroup.startAnimation(fadeAnimation)
|
||||
binding.topControlsGroup.isVisible = true
|
||||
|
||||
|
@ -91,11 +91,14 @@ class PlayerControlsView @JvmOverloads constructor(context: Context, attrs: Attr
|
|||
binding.bottomControlsGroup.startAnimation(fadeAnimation)
|
||||
binding.bottomControlsGroup.isVisible = true
|
||||
}
|
||||
showControls = false
|
||||
} else {
|
||||
showControls = true
|
||||
|
||||
animationHandler.removeCallbacks(controlsViewRunnable)
|
||||
animationHandler.postDelayed(controlsViewRunnable, 500L)
|
||||
animationHandler.removeCallbacks(nonSeekViewRunnable)
|
||||
animationHandler.postDelayed(nonSeekViewRunnable, 700L)
|
||||
animationHandler.postDelayed(nonSeekViewRunnable, 600L + resources.getInteger(R.integer.player_animation_duration).toLong())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,21 +284,38 @@ class PlayerControlsView @JvmOverloads constructor(context: Context, attrs: Attr
|
|||
|
||||
private fun fadeOutView(view: View) {
|
||||
animationHandler.removeCallbacks(controlsViewRunnable)
|
||||
AnimationUtils.loadAnimation(context, R.anim.fade_out_medium).also { fadeAnimation ->
|
||||
|
||||
AnimationUtils.loadAnimation(context, R.anim.player_fade_out).also { fadeAnimation ->
|
||||
view.startAnimation(fadeAnimation)
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.seekBarGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_exit_bottom))
|
||||
if (!showControls) {
|
||||
binding.topControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_exit_top))
|
||||
binding.bottomRightControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_exit_right))
|
||||
binding.bottomLeftControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_exit_left))
|
||||
binding.middleControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_fade_out))
|
||||
showControls = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun fadeInView(view: View) {
|
||||
animationHandler.removeCallbacks(controlsViewRunnable)
|
||||
AnimationUtils.loadAnimation(context, R.anim.fade_in_short).also { fadeAnimation ->
|
||||
|
||||
AnimationUtils.loadAnimation(context, R.anim.player_fade_in).also { fadeAnimation ->
|
||||
view.startAnimation(fadeAnimation)
|
||||
view.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
binding.seekBarGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_enter_bottom))
|
||||
binding.topControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_enter_top))
|
||||
binding.bottomRightControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_enter_right))
|
||||
binding.bottomLeftControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_enter_left))
|
||||
binding.middleControlsGroup.startAnimation(AnimationUtils.loadAnimation(context, R.anim.player_fade_in))
|
||||
}
|
||||
|
||||
internal fun pauseForDialog(): StateRestoreCallback {
|
||||
private fun pauseForDialog(): StateRestoreCallback {
|
||||
val wasPlayerPaused = activity.player.paused ?: true // default to not changing state
|
||||
activity.player.paused = true
|
||||
return {
|
||||
|
|
9
app/src/main/res/anim/player_enter_bottom.xml
Normal file
9
app/src/main/res/anim/player_enter_bottom.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in">
|
||||
|
||||
<translate
|
||||
android:fromYDelta="100%p"
|
||||
android:toYDelta="0" />
|
||||
</set>
|
9
app/src/main/res/anim/player_enter_left.xml
Normal file
9
app/src/main/res/anim/player_enter_left.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in">
|
||||
|
||||
<translate
|
||||
android:fromXDelta="-100%p"
|
||||
android:toXDelta="0" />
|
||||
</set>
|
9
app/src/main/res/anim/player_enter_right.xml
Normal file
9
app/src/main/res/anim/player_enter_right.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in">
|
||||
|
||||
<translate
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0" />
|
||||
</set>
|
9
app/src/main/res/anim/player_enter_top.xml
Normal file
9
app/src/main/res/anim/player_enter_top.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in">
|
||||
|
||||
<translate
|
||||
android:fromYDelta="-100%p"
|
||||
android:toYDelta="0" />
|
||||
</set>
|
8
app/src/main/res/anim/player_exit_bottom.xml
Normal file
8
app/src/main/res/anim/player_exit_bottom.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration">
|
||||
|
||||
<translate
|
||||
android:toYDelta="100%p"
|
||||
android:fromYDelta="0" />
|
||||
</set>
|
8
app/src/main/res/anim/player_exit_left.xml
Normal file
8
app/src/main/res/anim/player_exit_left.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration">
|
||||
|
||||
<translate
|
||||
android:toXDelta="-100%p"
|
||||
android:fromXDelta="0" />
|
||||
</set>
|
8
app/src/main/res/anim/player_exit_right.xml
Normal file
8
app/src/main/res/anim/player_exit_right.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration">
|
||||
|
||||
<translate
|
||||
android:toXDelta="100%p"
|
||||
android:fromXDelta="0" />
|
||||
</set>
|
8
app/src/main/res/anim/player_exit_top.xml
Normal file
8
app/src/main/res/anim/player_exit_top.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/player_animation_duration">
|
||||
|
||||
<translate
|
||||
android:toYDelta="-100%p"
|
||||
android:fromYDelta="0" />
|
||||
</set>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="150"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:interpolator="@android:interpolator/linear"/>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="150"
|
||||
android:duration="@integer/player_animation_duration"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:interpolator="@android:interpolator/linear"/>
|
|
@ -265,80 +265,83 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:layoutDirection="ltr"
|
||||
android:visibility="visible">
|
||||
|
||||
<!-- Bottom Controls (Right)-->
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/lockBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Lock player"
|
||||
android:src="@drawable/ic_lock_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/rotateBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Rotate player"
|
||||
android:onClick="rotatePlayer"
|
||||
android:src="@drawable/ic_screen_rotation_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/lockBtn"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/cycleSpeedBtn"
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomLeftControlsGroup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:onClick="cycleSpeed"
|
||||
android:text=".."
|
||||
android:textColor="?attr/colorOnPrimarySurface"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/rotateBtn" />
|
||||
app:layout_constraintLeft_toLeftOf="parent">
|
||||
|
||||
<!-- Top Controls (Left)-->
|
||||
<ImageButton
|
||||
android:id="@+id/lockBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Lock player"
|
||||
android:src="@drawable/ic_lock_24dp"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/pipBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_player_pip"
|
||||
android:src="@drawable/ic_picture_in_picture_24dp"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
<ImageButton
|
||||
android:id="@+id/rotateBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Rotate player"
|
||||
android:onClick="rotatePlayer"
|
||||
android:src="@drawable/ic_screen_rotation_24dp"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/cycleViewModeBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Cycle view modes"
|
||||
android:onClick="cycleViewMode"
|
||||
android:src="@drawable/ic_fullscreen_black_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/pipBtn"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
<Button
|
||||
android:id="@+id/cycleSpeedBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:onClick="cycleSpeed"
|
||||
android:text=".."
|
||||
android:textColor="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/controls_skip_intro_btn"
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomRightControlsGroup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:onClick="skipIntro"
|
||||
android:textColor="?attr/colorOnPrimarySurface"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/cycleViewModeBtn" />
|
||||
app:layout_constraintRight_toRightOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/controls_skip_intro_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:onClick="skipIntro"
|
||||
android:textColor="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/cycleViewModeBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="Cycle view modes"
|
||||
android:onClick="cycleViewMode"
|
||||
android:src="@drawable/ic_fullscreen_black_24dp"
|
||||
app:tint="?attr/colorOnPrimarySurface" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/pipBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_player_pip"
|
||||
android:src="@drawable/ic_picture_in_picture_24dp"
|
||||
android:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
4
app/src/main/res/values/integers.xml
Normal file
4
app/src/main/res/values/integers.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<integer name="player_animation_duration">200</integer>
|
||||
</resources>
|
Loading…
Reference in a new issue