Edge-to-edge manga details view (#5613)
* Prepare for edge-to-edge MangaController * Fix derpy liftToScroll with our own implementation * Edge-to-edge MangaController Except when legacy blue theme is used. * Save app bar lift state for controller backstack * Fix expanded cover position after the view recycled * Handle overlap changes when incognito mode disabled * Tablet fixes * Revert "Handle overlap changes when incognito mode disabled" This reverts commit 1f492449 Breaks on rotation changes. * Fix MangaController's swipe refresh position * All controllers are now doing lift app bar on scroll by default They are already doing that before so this pretty much just a cleanups. * TachiyomiCoordinatorLayout: Support ViewPager for app bar lift state check I'm willing to revert this if this minute detail solution is deemed too hacky xD * Fix app bar not lifted when scrolled without fling * Save app bar lift state across configuration changes * Fix MangaController's swipe refresh position after configuration change * TachiyomiCoordinatorLayout: Update ViewPager reference when controller is changed
This commit is contained in:
@@ -1,47 +1,87 @@
|
||||
package eu.kanade.tachiyomi.widget
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.StateListAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.google.android.material.R
|
||||
import com.google.android.material.animation.AnimationUtils
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
class ElevationAppBarLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : AppBarLayout(context, attrs) {
|
||||
|
||||
private var origStateAnimator: StateListAnimator? = null
|
||||
private var lifted = true
|
||||
private var transparent = false
|
||||
|
||||
init {
|
||||
origStateAnimator = stateListAnimator
|
||||
private val toolbar by lazy { findViewById<MaterialToolbar>(R.id.toolbar) }
|
||||
|
||||
private var elevationAnimator: ValueAnimator? = null
|
||||
private var backgroundAlphaAnimator: ValueAnimator? = null
|
||||
|
||||
var isTransparentWhenNotLifted = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
updateBackgroundAlpha()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disabled. Lift on scroll is handled manually with [TachiyomiCoordinatorLayout]
|
||||
*/
|
||||
override fun isLiftOnScroll(): Boolean = false
|
||||
|
||||
override fun isLifted(): Boolean = lifted
|
||||
|
||||
override fun setLifted(lifted: Boolean): Boolean {
|
||||
return if (this.lifted != lifted) {
|
||||
this.lifted = lifted
|
||||
val from = elevation
|
||||
val to = if (lifted) {
|
||||
resources.getDimension(R.dimen.design_appbar_elevation)
|
||||
} else {
|
||||
0F
|
||||
}
|
||||
|
||||
elevationAnimator?.cancel()
|
||||
elevationAnimator = ValueAnimator.ofFloat(from, to).apply {
|
||||
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
||||
interpolator = AnimationUtils.LINEAR_INTERPOLATOR
|
||||
addUpdateListener {
|
||||
elevation = it.animatedValue as Float
|
||||
}
|
||||
start()
|
||||
}
|
||||
|
||||
updateBackgroundAlpha()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun enableElevation(liftOnScroll: Boolean) {
|
||||
setElevation(liftOnScroll)
|
||||
}
|
||||
private fun updateBackgroundAlpha() {
|
||||
val newTransparent = if (lifted) false else isTransparentWhenNotLifted
|
||||
if (transparent != newTransparent) {
|
||||
transparent = newTransparent
|
||||
val fromAlpha = if (transparent) 255 else 0
|
||||
val toAlpha = if (transparent) 0 else 255
|
||||
|
||||
private fun setElevation(liftOnScroll: Boolean) {
|
||||
stateListAnimator = origStateAnimator
|
||||
isLiftOnScroll = liftOnScroll
|
||||
}
|
||||
|
||||
fun disableElevation() {
|
||||
stateListAnimator = StateListAnimator().apply {
|
||||
val objAnimator = ObjectAnimator.ofFloat(this, "elevation", 0f)
|
||||
|
||||
// Enabled and collapsible, but not collapsed means not elevated
|
||||
addState(
|
||||
intArrayOf(android.R.attr.enabled, R.attr.state_collapsible, -R.attr.state_collapsed),
|
||||
objAnimator
|
||||
)
|
||||
|
||||
// Default enabled state
|
||||
addState(intArrayOf(android.R.attr.enabled), objAnimator)
|
||||
|
||||
// Disabled state
|
||||
addState(IntArray(0), objAnimator)
|
||||
backgroundAlphaAnimator?.cancel()
|
||||
backgroundAlphaAnimator = ValueAnimator.ofInt(fromAlpha, toAlpha).apply {
|
||||
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
||||
interpolator = AnimationUtils.LINEAR_INTERPOLATOR
|
||||
addUpdateListener {
|
||||
val alpha = it.animatedValue as Int
|
||||
background.alpha = alpha
|
||||
toolbar?.background?.alpha = alpha
|
||||
statusBarForeground?.alpha = alpha
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user