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:
Ivan Iskandar
2021-08-19 20:12:52 +07:00
committed by GitHub
parent 914b686c8e
commit da16110e1c
20 changed files with 490 additions and 90 deletions
@@ -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()
}
}
}
}