Use standard BottomNav & Remove hide on scroll for AppBar and BottomNav

This commit is contained in:
RikkaW
2021-09-03 18:38:02 +08:00
committed by John Wu
parent 605189bc6e
commit 383192784d
8 changed files with 59 additions and 349 deletions
@@ -1,127 +0,0 @@
package com.topjohnwu.magisk.utils
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior
import com.google.android.material.snackbar.Snackbar
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Info
import kotlin.math.roundToInt
class HideBottomViewOnScrollBehavior<V : View>(context: Context, attrs: AttributeSet) :
HideBottomViewOnScrollBehavior<V>(), HideableBehavior<V> {
private var lockState: Boolean = false
private var isLaidOut = false
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View) =
super.layoutDependsOn(parent, child, dependency) or (dependency is Snackbar.SnackbarLayout)
override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
isLaidOut = true
return super.onLayoutChild(parent, child, layoutDirection)
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
child: V,
dependency: View
) = when (dependency) {
is Snackbar.SnackbarLayout -> onDependentViewChanged(parent, child, dependency)
else -> super.onDependentViewChanged(parent, child, dependency)
}
override fun onDependentViewRemoved(
parent: CoordinatorLayout,
child: V,
dependency: View
) = when (dependency) {
is Snackbar.SnackbarLayout -> onDependentViewRemoved(parent, child, dependency)
else -> super.onDependentViewRemoved(parent, child, dependency)
}
//---
private fun onDependentViewChanged(
parent: CoordinatorLayout,
child: V,
dependency: Snackbar.SnackbarLayout
): Boolean {
val viewMargin = (child.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin
val additionalMargin = dependency.resources.getDimension(R.dimen.l1).roundToInt()
val translation = dependency.height + additionalMargin
dependency.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = viewMargin
}
// checks whether the navigation is not hidden via scroll
if (child.isVisible && child.translationY <= 0) {
child.translationY(-translation.toFloat())
}
return false
}
private fun onDependentViewRemoved(
parent: CoordinatorLayout,
child: V,
dependency: Snackbar.SnackbarLayout
) {
// checks whether the navigation is not hidden via scroll
if (child.isVisible && child.translationY <= 0) {
child.translationY(0f)
}
}
//---
override fun slideUp(child: V) {
if (lockState) return
super.slideUp(child)
}
override fun slideDown(child: V) {
if (lockState) return
super.slideDown(child)
}
override fun setHidden(
view: V,
hide: Boolean,
lockState: Boolean
) {
if (!lockState) {
this.lockState = lockState
}
if (hide || !Info.env.isActive) {
// view is not laid out and drawn yet properly, so animation will not be attached
// hence we just simply hide the view
if (!isLaidOut) {
view.isGone = true
} else {
slideDown(view)
}
} else {
view.isVisible = Info.env.isActive
slideUp(view)
}
this.lockState = lockState
}
//---
private fun View.translationY(destination: Float) = animate()
.translationY(destination)
.setInterpolator(FastOutSlowInInterpolator())
.start()
}
@@ -1,143 +0,0 @@
package com.topjohnwu.magisk.utils
import android.animation.TimeInterpolator
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.ViewPropertyAnimator
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import com.google.android.material.animation.AnimationUtils
class HideTopViewOnScrollBehavior<V : View>(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<V>(), HideableBehavior<V> {
companion object {
private const val STATE_SCROLLED_DOWN = 1
private const val STATE_SCROLLED_UP = 2
private const val ENTER_ANIMATION_DURATION = 225
private const val EXIT_ANIMATION_DURATION = 175
}
private var height = 0
private var currentState = STATE_SCROLLED_UP
private var currentAnimator: ViewPropertyAnimator? = null
private var lockState: Boolean = false
override fun onLayoutChild(
parent: CoordinatorLayout,
child: V,
layoutDirection: Int
): Boolean {
val paramsCompat = child.layoutParams as ViewGroup.MarginLayoutParams
height = child.measuredHeight + paramsCompat.topMargin
return super.onLayoutChild(parent, child, layoutDirection)
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
directTargetChild: View,
target: View,
nestedScrollAxes: Int,
type: Int
) = nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
override fun onNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
dxConsumed: Int,
dyConsumed: Int,
dxUnconsumed: Int,
dyUnconsumed: Int,
type: Int,
consumed: IntArray
) {
// when initiating scroll while the view is at the bottom or at the top and pushing it
// further, the parent will report consumption of 0
if (dyConsumed == 0) return
setHidden(child, dyConsumed > 0, false)
}
@Suppress("UNCHECKED_CAST")
override fun setHidden(
view: V,
hide: Boolean,
lockState: Boolean
) {
if (!lockState) {
this.lockState = lockState
}
if (hide) {
slideUp(view)
} else {
slideDown(view)
}
this.lockState = lockState
}
/**
* Perform an animation that will slide the child from it's current position to be totally on the
* screen.
*/
private fun slideDown(child: V) {
if (currentState == STATE_SCROLLED_UP || lockState) {
return
}
currentAnimator?.let {
it.cancel()
child.clearAnimation()
}
currentState = STATE_SCROLLED_UP
animateChildTo(
child,
0,
ENTER_ANIMATION_DURATION.toLong(),
AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR
)
}
/**
* Perform an animation that will slide the child from it's current position to be totally off the
* screen.
*/
private fun slideUp(child: V) {
if (currentState == STATE_SCROLLED_DOWN || lockState) {
return
}
currentAnimator?.let {
it.cancel()
child.clearAnimation()
}
currentState = STATE_SCROLLED_DOWN
animateChildTo(
child,
-height,
EXIT_ANIMATION_DURATION.toLong(),
AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR
)
}
private fun animateChildTo(
child: V,
targetY: Int,
duration: Long,
interpolator: TimeInterpolator
) = child
.animate()
.translationY(targetY.toFloat())
.setInterpolator(interpolator)
.setDuration(duration)
.withEndAction { currentAnimator = null }
.let { currentAnimator = it }
}