Better BottomNavigationView hide/unhide animation
This commit is contained in:
parent
e7f700ee9a
commit
95e39e4f4c
2 changed files with 87 additions and 8 deletions
|
@ -366,18 +366,15 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
)
|
||||
return
|
||||
}
|
||||
val translationY =
|
||||
if (visible) 0F else dip(R.dimen.bottom_nav_height).toFloat() + windowInsets.safeGetBottomInsets()
|
||||
val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED
|
||||
if (mAnimate) {
|
||||
binding.bottomNavigationView.translateYAnimate(translationY).doOnEnd {
|
||||
if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
|
||||
binding.bottomNavigationView.bringToFront()
|
||||
}
|
||||
if (visible) {
|
||||
binding.bottomNavigationView.bringToFront()
|
||||
binding.bottomNavigationView.show()
|
||||
} else {
|
||||
binding.bottomNavigationView.hide()
|
||||
}
|
||||
} else {
|
||||
binding.bottomNavigationView.translationY =
|
||||
translationY
|
||||
binding.bottomNavigationView.isVisible = false
|
||||
if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
|
||||
binding.bottomNavigationView.bringToFront()
|
||||
|
|
|
@ -16,10 +16,13 @@ package code.name.monkey.retromusic.extensions
|
|||
|
||||
import android.animation.Animator
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.annotation.LayoutRes
|
||||
|
@ -32,6 +35,7 @@ import code.name.monkey.appthemehelper.ThemeStore
|
|||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
|
||||
|
@ -58,6 +62,84 @@ fun EditText.appHandleColor(): EditText {
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially animate showing a [BottomNavigationView].
|
||||
*
|
||||
* Abruptly changing the visibility leads to a re-layout of main content, animating
|
||||
* `translationY` leaves a gap where the view was that content does not fill.
|
||||
*
|
||||
* Instead, take a snapshot of the view, and animate this in, only changing the visibility (and
|
||||
* thus layout) when the animation completes.
|
||||
*/
|
||||
fun BottomNavigationView.show() {
|
||||
if (isVisible) return
|
||||
|
||||
val parent = parent as ViewGroup
|
||||
// View needs to be laid out to create a snapshot & know position to animate. If view isn't
|
||||
// laid out yet, need to do this manually.
|
||||
if (!isLaidOut) {
|
||||
measure(
|
||||
View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.EXACTLY),
|
||||
View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.AT_MOST)
|
||||
)
|
||||
layout(parent.left, parent.height - measuredHeight, parent.right, parent.height)
|
||||
}
|
||||
|
||||
val drawable = BitmapDrawable(context.resources, drawToBitmap())
|
||||
drawable.setBounds(left, parent.height, right, parent.height + height)
|
||||
parent.overlay.add(drawable)
|
||||
ValueAnimator.ofInt(parent.height, top).apply {
|
||||
duration = 300
|
||||
interpolator = AnimationUtils.loadInterpolator(
|
||||
context,
|
||||
android.R.interpolator.linear_out_slow_in
|
||||
)
|
||||
addUpdateListener {
|
||||
val newTop = it.animatedValue as Int
|
||||
drawable.setBounds(left, newTop, right, newTop + height)
|
||||
}
|
||||
doOnEnd {
|
||||
parent.overlay.remove(drawable)
|
||||
isVisible = true
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially animate hiding a [BottomNavigationView].
|
||||
*
|
||||
* Abruptly changing the visibility leads to a re-layout of main content, animating
|
||||
* `translationY` leaves a gap where the view was that content does not fill.
|
||||
*
|
||||
* Instead, take a snapshot, instantly hide the view (so content lays out to fill), then animate
|
||||
* out the snapshot.
|
||||
*/
|
||||
fun BottomNavigationView.hide() {
|
||||
if (isGone) return
|
||||
|
||||
val drawable = BitmapDrawable(context.resources, drawToBitmap())
|
||||
val parent = parent as ViewGroup
|
||||
drawable.setBounds(left, top, right, bottom)
|
||||
parent.overlay.add(drawable)
|
||||
isGone = true
|
||||
ValueAnimator.ofInt(top, parent.height).apply {
|
||||
duration = 300L
|
||||
interpolator = AnimationUtils.loadInterpolator(
|
||||
context,
|
||||
android.R.interpolator.fast_out_linear_in
|
||||
)
|
||||
addUpdateListener {
|
||||
val newTop = it.animatedValue as Int
|
||||
drawable.setBounds(left, newTop, right, newTop + height)
|
||||
}
|
||||
doOnEnd {
|
||||
parent.overlay.remove(drawable)
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun View.translateYAnimate(value: Float): Animator {
|
||||
return ObjectAnimator.ofFloat(this, "translationY", value)
|
||||
.apply {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue