Use Compose to animate bottom reader menu bars
(cherry picked from commit 97b4d1f13de194163d7dc13a0d73d023109bc8c2) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt # app/src/main/res/anim/enter_from_bottom.xml # app/src/main/res/anim/exit_to_bottom.xml
This commit is contained in:
parent
abd97efe85
commit
e427dc2d1c
@ -31,6 +31,10 @@ import android.widget.RelativeLayout
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
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
|
||||||
@ -311,7 +315,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -321,7 +325,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,68 +653,74 @@ class ReaderActivity : BaseActivity() {
|
|||||||
val readerBottomButtons by readerPreferences.readerBottomButtons().collectAsState()
|
val readerBottomButtons by readerPreferences.readerBottomButtons().collectAsState()
|
||||||
val dualPageSplitPaged by readerPreferences.dualPageSplitPaged().collectAsState()
|
val dualPageSplitPaged by readerPreferences.dualPageSplitPaged().collectAsState()
|
||||||
|
|
||||||
Column(
|
AnimatedVisibility(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
visible = state.menuVisible,
|
||||||
|
enter = slideInVertically(
|
||||||
|
initialOffsetY = { it },
|
||||||
|
animationSpec = tween(200),
|
||||||
|
),
|
||||||
|
exit = slideOutVertically(
|
||||||
|
targetOffsetY = { it },
|
||||||
|
animationSpec = tween(200),
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
// SY -->
|
Column(
|
||||||
sliderContent(false)
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
// SY <--
|
) {
|
||||||
|
|
||||||
BottomReaderBar(
|
|
||||||
enabledButtons = readerBottomButtons,
|
|
||||||
readingMode = ReadingModeType.fromPreference(
|
|
||||||
viewModel.getMangaReadingMode(
|
|
||||||
resolveDefault = false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onClickReadingMode = viewModel::openReadingModeSelectDialog,
|
|
||||||
orientationMode = OrientationType.fromPreference(
|
|
||||||
viewModel.getMangaOrientationType(
|
|
||||||
resolveDefault = false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onClickOrientationMode = viewModel::openOrientationModeSelectDialog,
|
|
||||||
cropEnabled = cropEnabled,
|
|
||||||
onClickCropBorder = {
|
|
||||||
val enabled = viewModel.toggleCropBorders()
|
|
||||||
|
|
||||||
menuToggleToast?.cancel()
|
|
||||||
menuToggleToast = toast(
|
|
||||||
if (enabled) {
|
|
||||||
R.string.on
|
|
||||||
} else {
|
|
||||||
R.string.off
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onClickSettings = viewModel::openSettingsDialog,
|
|
||||||
// SY -->
|
// SY -->
|
||||||
isHttpSource = remember {
|
sliderContent(false)
|
||||||
viewModel.getSource() != null
|
|
||||||
},
|
|
||||||
dualPageSplitEnabled = dualPageSplitPaged,
|
|
||||||
doublePages = state.doublePages,
|
|
||||||
onClickChapterList = viewModel::openChapterListDialog,
|
|
||||||
onClickWebView = ::openChapterInWebView,
|
|
||||||
onClickShare = {
|
|
||||||
assistUrl?.let {
|
|
||||||
val intent = it.toUri().toShareIntent(this@ReaderActivity, type = "text/plain")
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClickPageLayout = {
|
|
||||||
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
|
||||||
(viewModel.state.value.viewer as? PagerViewer)?.config?.let { config ->
|
|
||||||
config.doublePages = !config.doublePages
|
|
||||||
reloadChapters(config.doublePages, true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
readerPreferences.pageLayout().set(1 - readerPreferences.pageLayout().get())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClickShiftPage = ::shiftDoublePages,
|
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
|
||||||
|
BottomReaderBar(
|
||||||
|
// SY -->
|
||||||
|
enabledButtons = readerBottomButtons,
|
||||||
|
// SY <--
|
||||||
|
readingMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false)),
|
||||||
|
onClickReadingMode = viewModel::openReadingModeSelectDialog,
|
||||||
|
orientationMode = OrientationType.fromPreference(viewModel.getMangaOrientationType(resolveDefault = false)),
|
||||||
|
onClickOrientationMode = viewModel::openOrientationModeSelectDialog,
|
||||||
|
cropEnabled = cropEnabled,
|
||||||
|
onClickCropBorder = {
|
||||||
|
val enabled = viewModel.toggleCropBorders()
|
||||||
|
|
||||||
|
menuToggleToast?.cancel()
|
||||||
|
menuToggleToast = toast(
|
||||||
|
if (enabled) {
|
||||||
|
R.string.on
|
||||||
|
} else {
|
||||||
|
R.string.off
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClickSettings = viewModel::openSettingsDialog,
|
||||||
|
// SY -->
|
||||||
|
isHttpSource = remember {
|
||||||
|
viewModel.getSource() != null
|
||||||
|
},
|
||||||
|
dualPageSplitEnabled = dualPageSplitPaged,
|
||||||
|
doublePages = state.doublePages,
|
||||||
|
onClickChapterList = viewModel::openChapterListDialog,
|
||||||
|
onClickWebView = ::openChapterInWebView,
|
||||||
|
onClickShare = {
|
||||||
|
assistUrl?.let {
|
||||||
|
val intent = it.toUri().toShareIntent(this@ReaderActivity, type = "text/plain")
|
||||||
|
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClickPageLayout = {
|
||||||
|
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
||||||
|
(viewModel.state.value.viewer as? PagerViewer)?.config?.let { config ->
|
||||||
|
config.doublePages = !config.doublePages
|
||||||
|
reloadChapters(config.doublePages, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
readerPreferences.pageLayout().set(1 - readerPreferences.pageLayout().get())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClickShiftPage = ::shiftDoublePages,
|
||||||
|
// SY <--
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,74 +952,46 @@ class ReaderActivity : BaseActivity() {
|
|||||||
// EXH <--
|
// EXH <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
}
|
||||||
}
|
},
|
||||||
},
|
)
|
||||||
)
|
// EXH -->
|
||||||
// EXH -->
|
binding.header.startAnimation(toolbarAnimation)
|
||||||
binding.header.startAnimation(toolbarAnimation)
|
// EXH <--
|
||||||
// EXH <--
|
|
||||||
|
|
||||||
val vertAnimation = AnimationUtils.loadAnimation(this, R.anim.fade_in_side)
|
|
||||||
val vertAnimationLeft = AnimationUtils.loadAnimation(this, R.anim.fade_in_side_left)
|
|
||||||
if (readerPreferences.leftVerticalSeekbar().get() && binding.readerNavVert.isVisible) {
|
|
||||||
binding.seekbarVertContainer.startAnimation(vertAnimationLeft)
|
|
||||||
} else {
|
|
||||||
binding.seekbarVertContainer.startAnimation(vertAnimation)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
}
|
||||||
}
|
},
|
||||||
},
|
)
|
||||||
)
|
// EXH -->
|
||||||
// EXH -->
|
binding.header.startAnimation(toolbarAnimation)
|
||||||
binding.header.startAnimation(toolbarAnimation)
|
// EXH <--
|
||||||
// EXH <--
|
|
||||||
|
|
||||||
val vertAnimation = AnimationUtils.loadAnimation(this, R.anim.fade_out_side)
|
|
||||||
val vertAnimationLeft = AnimationUtils.loadAnimation(this, R.anim.fade_out_side_left)
|
|
||||||
if (readerPreferences.leftVerticalSeekbar().get() && binding.readerNavVert.isVisible) {
|
|
||||||
binding.seekbarVertContainer.startAnimation(vertAnimationLeft)
|
|
||||||
} else {
|
|
||||||
binding.seekbarVertContainer.startAnimation(vertAnimation)
|
|
||||||
}
|
|
||||||
|
|
||||||
val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom)
|
|
||||||
bottomAnimation.applySystemAnimatorScale(this)
|
|
||||||
binding.readerMenuBottom.startAnimation(bottomAnimation)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
|
@ -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>
|
|
Loading…
x
Reference in New Issue
Block a user