Use Compose to animate bottom reader menu bars

This commit is contained in:
arkon 2023-10-09 22:27:46 -04:00
parent 79b37df647
commit 97b4d1f13d
3 changed files with 75 additions and 88 deletions

View file

@ -24,6 +24,10 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -249,7 +253,7 @@ class ReaderActivity : BaseActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
viewModel.restartReadTimer() viewModel.restartReadTimer()
setMenuVisibility(viewModel.state.value.menuVisible, animate = false) setMenuVisibility(viewModel.state.value.menuVisible)
} }
/** /**
@ -259,7 +263,7 @@ class ReaderActivity : BaseActivity() {
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus) super.onWindowFocusChanged(hasFocus)
if (hasFocus) { if (hasFocus) {
setMenuVisibility(viewModel.state.value.menuVisible, animate = false) setMenuVisibility(viewModel.state.value.menuVisible)
} }
} }
@ -473,43 +477,55 @@ class ReaderActivity : BaseActivity() {
val isPagerType = ReadingModeType.isPagerType(viewModel.getMangaReadingMode()) val isPagerType = ReadingModeType.isPagerType(viewModel.getMangaReadingMode())
val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon
Column( AnimatedVisibility(
verticalArrangement = Arrangement.spacedBy(8.dp), visible = state.menuVisible,
enter = slideInVertically(
initialOffsetY = { it },
animationSpec = tween(200),
),
exit = slideOutVertically(
targetOffsetY = { it },
animationSpec = tween(200),
),
) { ) {
ChapterNavigator( Column(
isRtl = isRtl, verticalArrangement = Arrangement.spacedBy(8.dp),
onNextChapter = ::loadNextChapter, ) {
enabledNext = state.viewerChapters?.nextChapter != null, ChapterNavigator(
onPreviousChapter = ::loadPreviousChapter, isRtl = isRtl,
enabledPrevious = state.viewerChapters?.prevChapter != null, onNextChapter = ::loadNextChapter,
currentPage = state.currentPage, enabledNext = state.viewerChapters?.nextChapter != null,
totalPages = state.totalPages, onPreviousChapter = ::loadPreviousChapter,
onSliderValueChange = { enabledPrevious = state.viewerChapters?.prevChapter != null,
isScrollingThroughPages = true currentPage = state.currentPage,
moveToPageIndex(it) totalPages = state.totalPages,
}, onSliderValueChange = {
) isScrollingThroughPages = true
moveToPageIndex(it)
},
)
BottomReaderBar( BottomReaderBar(
readingMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false)), readingMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false)),
onClickReadingMode = viewModel::openReadingModeSelectDialog, onClickReadingMode = viewModel::openReadingModeSelectDialog,
orientationMode = OrientationType.fromPreference(viewModel.getMangaOrientationType(resolveDefault = false)), orientationMode = OrientationType.fromPreference(viewModel.getMangaOrientationType(resolveDefault = false)),
onClickOrientationMode = viewModel::openOrientationModeSelectDialog, onClickOrientationMode = viewModel::openOrientationModeSelectDialog,
cropEnabled = cropEnabled, cropEnabled = cropEnabled,
onClickCropBorder = { onClickCropBorder = {
val enabled = viewModel.toggleCropBorders() val enabled = viewModel.toggleCropBorders()
menuToggleToast?.cancel() menuToggleToast?.cancel()
menuToggleToast = toast( menuToggleToast = toast(
if (enabled) { if (enabled) {
R.string.on R.string.on
} else { } else {
R.string.off R.string.off
}, },
) )
}, },
onClickSettings = viewModel::openSettingsDialog, onClickSettings = viewModel::openSettingsDialog,
) )
}
} }
} }
@ -531,54 +547,41 @@ class ReaderActivity : BaseActivity() {
} }
/** /**
* Sets the visibility of the menu according to [visible] and with an optional parameter to * Sets the visibility of the menu according to [visible].
* [animate] the views.
*/ */
private fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { private fun setMenuVisibility(visible: Boolean) {
viewModel.showMenus(visible) viewModel.showMenus(visible)
if (visible) { if (visible) {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
binding.readerMenu.isVisible = true binding.readerMenu.isVisible = true
if (animate) { val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top) toolbarAnimation.applySystemAnimatorScale(this)
toolbarAnimation.applySystemAnimatorScale(this) toolbarAnimation.setAnimationListener(
toolbarAnimation.setAnimationListener( object : SimpleAnimationListener() {
object : SimpleAnimationListener() { override fun onAnimationStart(animation: Animation) {
override fun onAnimationStart(animation: Animation) { // Fix status bar being translucent the first time it's opened.
// Fix status bar being translucent the first time it's opened. window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) }
} },
}, )
) binding.toolbar.startAnimation(toolbarAnimation)
binding.toolbar.startAnimation(toolbarAnimation)
val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom)
bottomAnimation.applySystemAnimatorScale(this)
binding.readerMenuBottom.startAnimation(bottomAnimation)
}
} else { } else {
if (readerPreferences.fullscreen().get()) { if (readerPreferences.fullscreen().get()) {
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} }
if (animate) { val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top)
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top) toolbarAnimation.applySystemAnimatorScale(this)
toolbarAnimation.applySystemAnimatorScale(this) toolbarAnimation.setAnimationListener(
toolbarAnimation.setAnimationListener( object : SimpleAnimationListener() {
object : SimpleAnimationListener() { override fun onAnimationEnd(animation: Animation) {
override fun onAnimationEnd(animation: Animation) { binding.readerMenu.isVisible = false
binding.readerMenu.isVisible = false }
} },
}, )
) binding.toolbar.startAnimation(toolbarAnimation)
binding.toolbar.startAnimation(toolbarAnimation)
val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom)
bottomAnimation.applySystemAnimatorScale(this)
binding.readerMenuBottom.startAnimation(bottomAnimation)
}
} }
} }

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="200"
android:fromYDelta="100%"
android:toYDelta="0%" />
</set>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="200"
android:fromYDelta="0%"
android:toYDelta="100%" />
</set>