From a68f12359436f0b57b50482687553f0a0b01845c Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Fri, 28 Jan 2022 22:14:13 +0700 Subject: [PATCH] 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. --- .../tachiyomi/widget/TachiyomiAppBarLayout.kt | 88 +++++++++++++------ 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiAppBarLayout.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiAppBarLayout.kt index 56bf8d633..e073cee62 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiAppBarLayout.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiAppBarLayout.kt @@ -6,13 +6,16 @@ import android.animation.AnimatorSet import android.animation.ValueAnimator import android.annotation.SuppressLint import android.content.Context +import android.graphics.Canvas +import android.graphics.drawable.Drawable import android.util.AttributeSet +import android.view.animation.LinearInterpolator import android.widget.TextView import androidx.annotation.FloatRange import androidx.lifecycle.coroutineScope import androidx.lifecycle.findViewTreeLifecycleOwner -import com.google.android.material.animation.AnimationUtils import com.google.android.material.shape.MaterialShapeDrawable +import dev.chrisbanes.insetter.applyInsetter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.view.findChild import kotlinx.coroutines.flow.launchIn @@ -50,28 +53,7 @@ class TachiyomiAppBarLayout @JvmOverloads constructor( private var animatorSet: AnimatorSet? = null private var statusBarForegroundAnimator: ValueAnimator? = null - private val offsetListener = OnOffsetChangedListener { appBarLayout, verticalOffset -> - // 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() - } - } - } + private var currentOffset = 0 var isTransparentWhenNotLifted = false set(value) { @@ -100,9 +82,47 @@ class TachiyomiAppBarLayout @JvmOverloads constructor( 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() { super.onAttachedToWindow() - addOnOffsetChangedListener(offsetListener) toolbar.background.alpha = 0 // Use app bar background titleTextView = toolbar.findChild() @@ -126,9 +146,9 @@ class TachiyomiAppBarLayout @JvmOverloads constructor( } } - override fun onDetachedFromWindow() { - super.onDetachedFromWindow() - removeOnOffsetChangedListener(offsetListener) + override fun setStatusBarForeground(drawable: Drawable?) { + super.setStatusBarForeground(drawable) + setWillNotDraw(statusBarForeground == null) } @SuppressLint("Recycle") @@ -168,7 +188,7 @@ class TachiyomiAppBarLayout @JvmOverloads constructor( animatorSet?.cancel() animatorSet = AnimatorSet().apply { duration = resources.getInteger(R.integer.app_bar_elevation_anim_duration).toLong() - interpolator = AnimationUtils.LINEAR_INTERPOLATOR + interpolator = LINEAR_INTERPOLATOR playTogether(*animators.toTypedArray()) start() } @@ -177,5 +197,17 @@ class TachiyomiAppBarLayout @JvmOverloads constructor( init { statusBarForeground = MaterialShapeDrawable.createWithElevationOverlay(context) + applyInsetter { + type(navigationBars = true) { + margin(horizontal = true) + } + type(statusBars = true) { + padding(top = true) + } + } + } + + companion object { + private val LINEAR_INTERPOLATOR = LinearInterpolator() } }