TachiyomiAppBarLayout: Use insetter to handle inset (#6506)
This requires adding the status bar foreground drawing logic since the parent class wouldn't know the inset changes anymore.
This commit is contained in:
parent
08ad4f96b9
commit
a68f123594
1 changed files with 60 additions and 28 deletions
|
@ -6,13 +6,16 @@ import android.animation.AnimatorSet
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.view.animation.LinearInterpolator
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.FloatRange
|
import androidx.annotation.FloatRange
|
||||||
import androidx.lifecycle.coroutineScope
|
import androidx.lifecycle.coroutineScope
|
||||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||||
import com.google.android.material.animation.AnimationUtils
|
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.util.view.findChild
|
import eu.kanade.tachiyomi.util.view.findChild
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -50,28 +53,7 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
|
||||||
private var animatorSet: AnimatorSet? = null
|
private var animatorSet: AnimatorSet? = null
|
||||||
|
|
||||||
private var statusBarForegroundAnimator: ValueAnimator? = null
|
private var statusBarForegroundAnimator: ValueAnimator? = null
|
||||||
private val offsetListener = OnOffsetChangedListener { appBarLayout, verticalOffset ->
|
private var currentOffset = 0
|
||||||
// Show status bar foreground when offset
|
|
||||||
val foreground = (appBarLayout?.statusBarForeground as? MaterialShapeDrawable) ?: return@OnOffsetChangedListener
|
|
||||||
val start = foreground.alpha
|
|
||||||
val end = if (verticalOffset != 0) 255 else 0
|
|
||||||
|
|
||||||
statusBarForegroundAnimator?.cancel()
|
|
||||||
if (animatorSet?.isRunning == true) {
|
|
||||||
foreground.alpha = end
|
|
||||||
return@OnOffsetChangedListener
|
|
||||||
}
|
|
||||||
if (start != end) {
|
|
||||||
statusBarForegroundAnimator = ValueAnimator.ofInt(start, end).apply {
|
|
||||||
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
|
||||||
interpolator = AnimationUtils.LINEAR_INTERPOLATOR
|
|
||||||
addUpdateListener {
|
|
||||||
foreground.alpha = it.animatedValue as Int
|
|
||||||
}
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isTransparentWhenNotLifted = false
|
var isTransparentWhenNotLifted = false
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -100,9 +82,47 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
|
||||||
|
|
||||||
override fun setLiftedState(lifted: Boolean, force: Boolean): Boolean = false
|
override fun setLiftedState(lifted: Boolean, force: Boolean): Boolean = false
|
||||||
|
|
||||||
|
override fun draw(canvas: Canvas) {
|
||||||
|
super.draw(canvas)
|
||||||
|
val saveCount = canvas.save()
|
||||||
|
canvas.translate(0f, -currentOffset.toFloat())
|
||||||
|
statusBarForeground?.draw(canvas)
|
||||||
|
canvas.restoreToCount(saveCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||||
|
super.onLayout(changed, l, t, r, b)
|
||||||
|
statusBarForeground?.setBounds(0, 0, width, paddingTop)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOffsetChanged(offset: Int) {
|
||||||
|
currentOffset = offset
|
||||||
|
super.onOffsetChanged(offset)
|
||||||
|
|
||||||
|
// Show status bar foreground when offset
|
||||||
|
val foreground = (statusBarForeground as? MaterialShapeDrawable) ?: return
|
||||||
|
val start = foreground.alpha
|
||||||
|
val end = if (offset != 0) 255 else 0
|
||||||
|
|
||||||
|
statusBarForegroundAnimator?.cancel()
|
||||||
|
if (animatorSet?.isRunning == true) {
|
||||||
|
foreground.alpha = end
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (start != end) {
|
||||||
|
statusBarForegroundAnimator = ValueAnimator.ofInt(start, end).apply {
|
||||||
|
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
||||||
|
interpolator = LINEAR_INTERPOLATOR
|
||||||
|
addUpdateListener {
|
||||||
|
foreground.alpha = it.animatedValue as Int
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
super.onAttachedToWindow()
|
super.onAttachedToWindow()
|
||||||
addOnOffsetChangedListener(offsetListener)
|
|
||||||
toolbar.background.alpha = 0 // Use app bar background
|
toolbar.background.alpha = 0 // Use app bar background
|
||||||
|
|
||||||
titleTextView = toolbar.findChild<TextView>()
|
titleTextView = toolbar.findChild<TextView>()
|
||||||
|
@ -126,9 +146,9 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetachedFromWindow() {
|
override fun setStatusBarForeground(drawable: Drawable?) {
|
||||||
super.onDetachedFromWindow()
|
super.setStatusBarForeground(drawable)
|
||||||
removeOnOffsetChangedListener(offsetListener)
|
setWillNotDraw(statusBarForeground == null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("Recycle")
|
@SuppressLint("Recycle")
|
||||||
|
@ -168,7 +188,7 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
|
||||||
animatorSet?.cancel()
|
animatorSet?.cancel()
|
||||||
animatorSet = AnimatorSet().apply {
|
animatorSet = AnimatorSet().apply {
|
||||||
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong()
|
||||||
interpolator = AnimationUtils.LINEAR_INTERPOLATOR
|
interpolator = LINEAR_INTERPOLATOR
|
||||||
playTogether(*animators.toTypedArray())
|
playTogether(*animators.toTypedArray())
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
|
@ -177,5 +197,17 @@ class TachiyomiAppBarLayout @JvmOverloads constructor(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
statusBarForeground = MaterialShapeDrawable.createWithElevationOverlay(context)
|
statusBarForeground = MaterialShapeDrawable.createWithElevationOverlay(context)
|
||||||
|
applyInsetter {
|
||||||
|
type(navigationBars = true) {
|
||||||
|
margin(horizontal = true)
|
||||||
|
}
|
||||||
|
type(statusBars = true) {
|
||||||
|
padding(top = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LINEAR_INTERPOLATOR = LinearInterpolator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue