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:
Ivan Iskandar 2022-01-28 22:14:13 +07:00 committed by GitHub
parent 08ad4f96b9
commit a68f123594
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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()
} }
} }