[BottomNavigation] Better animations for BottomNavigationView

This commit is contained in:
Prathamesh More 2021-12-02 23:56:07 +05:30
parent e02e99ed02
commit 91a4282581
5 changed files with 27 additions and 38 deletions

View file

@ -110,7 +110,7 @@ dependencies {
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
def room_version = '2.4.0-beta02' def room_version = '2.4.0-rc01'
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version" implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version" kapt "androidx.room:room-compiler:$room_version"

View file

@ -134,8 +134,6 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
PreferenceUtil.registerOnSharedPreferenceChangedListener(this) PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
val expand = extra<Boolean>(EXPAND_PANEL).value ?: false val expand = extra<Boolean>(EXPAND_PANEL).value ?: false
if (expand && PreferenceUtil.isExpandPanel) { if (expand && PreferenceUtil.isExpandPanel) {
setBottomNavVisibility(false)
fromNotification = true
expandPanel() expandPanel()
intent.removeExtra(EXPAND_PANEL) intent.removeExtra(EXPAND_PANEL)
} }

View file

@ -14,7 +14,6 @@
*/ */
package code.name.monkey.retromusic.activities.base package code.name.monkey.retromusic.activities.base
import android.animation.Animator
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
@ -67,11 +66,9 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() { abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
companion object { companion object {
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
var fromNotification: Boolean = false
} }
private var windowInsets: WindowInsetsCompat? = null private var windowInsets: WindowInsetsCompat? = null
private var bottomNavAnimator: Animator? = null
protected val libraryViewModel by viewModel<LibraryViewModel>() protected val libraryViewModel by viewModel<LibraryViewModel>()
private lateinit var bottomSheetBehavior: RetroBottomSheetBehavior<FrameLayout> private lateinit var bottomSheetBehavior: RetroBottomSheetBehavior<FrameLayout>
private var playerFragment: AbsPlayerFragment? = null private var playerFragment: AbsPlayerFragment? = null
@ -96,15 +93,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
STATE_COLLAPSED -> { STATE_COLLAPSED -> {
onPanelCollapsed() onPanelCollapsed()
if (fromNotification) {
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty())
fromNotification = false
}
}
STATE_SETTLING, STATE_DRAGGING -> {
if (fromNotification) {
bottomNavigationView.isVisible = true
}
} }
else -> { else -> {
println("Do something") println("Do something")
@ -319,53 +307,55 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false) { fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false) {
binding.bottomNavigationView.isVisible = visible binding.bottomNavigationView.translateYAnimate(if (visible) 0F else dip(R.dimen.bottom_nav_height).toFloat() + windowInsets.safeGetBottomInsets())
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty(), animate) .apply {
doOnEnd {
binding.bottomNavigationView.bringToFront()
}
hideBottomSheet(
hide = MusicPlayerRemote.playingQueue.isEmpty(),
animate = animate,
isBottomNavVisible = visible
)
}
} }
fun hideBottomSheet(hide: Boolean, animate: Boolean = false) { fun hideBottomSheet(
hide: Boolean,
animate: Boolean = false,
isBottomNavVisible: Boolean = bottomNavigationView.isVisible
) {
val heightOfBar = val heightOfBar =
windowInsets.safeGetBottomInsets() + windowInsets.safeGetBottomInsets() +
if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height) if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height)
val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height) val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height)
val isVisible = binding.bottomNavigationView.isVisible
if (hide) { if (hide) {
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets() bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
bottomSheetBehavior.state = STATE_COLLAPSED bottomSheetBehavior.state = STATE_COLLAPSED
libraryViewModel.setFabMargin(if (isVisible) dip(R.dimen.bottom_nav_height) else 0) libraryViewModel.setFabMargin(if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0)
ViewCompat.setElevation(binding.slidingPanel, 0f) ViewCompat.setElevation(binding.slidingPanel, 0f)
ViewCompat.setElevation(binding.bottomNavigationView, 10f) ViewCompat.setElevation(binding.bottomNavigationView, 10f)
} else { } else {
if (MusicPlayerRemote.playingQueue.isNotEmpty()) { if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
ViewCompat.setElevation(binding.slidingPanel, 10f) ViewCompat.setElevation(binding.slidingPanel, 10f)
ViewCompat.setElevation(binding.bottomNavigationView, 10f) ViewCompat.setElevation(binding.bottomNavigationView, 10f)
if (isVisible) { if (isBottomNavVisible) {
println("List") println("List")
if (animate) { if (animate) {
bottomNavAnimator?.end()
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs) bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
bottomNavAnimator = binding.bottomNavigationView.translateYAnimate(0F)
} else { } else {
bottomSheetBehavior.peekHeight = heightOfBarWithTabs bottomSheetBehavior.peekHeight = heightOfBarWithTabs
binding.bottomNavigationView.translationY = 0F
} }
binding.bottomNavigationView.bringToFront() binding.bottomNavigationView.bringToFront()
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height_expanded)) libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height_expanded))
} else { } else {
println("Details") println("Details")
if (animate) { if (animate) {
bottomSheetBehavior.peekHeightAnimate(heightOfBar) bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd {
bottomNavAnimator?.end()
bottomNavAnimator =
bottomNavigationView.translateYAnimate(dip(R.dimen.bottom_nav_height).toFloat())
bottomNavAnimator?.doOnEnd {
binding.slidingPanel.bringToFront() binding.slidingPanel.bringToFront()
} }
} else { } else {
bottomSheetBehavior.peekHeight = heightOfBar bottomSheetBehavior.peekHeight = heightOfBar
binding.bottomNavigationView.translationY =
dip(R.dimen.bottom_nav_height).toFloat()
binding.slidingPanel.bringToFront() binding.slidingPanel.bringToFront()
} }
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height)) libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height))

View file

@ -37,6 +37,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.ShapeAppearanceModel import com.google.android.material.shape.ShapeAppearanceModel
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T { fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
return LayoutInflater.from(context).inflate(layout, this, false) as T return LayoutInflater.from(context).inflate(layout, this, false) as T
@ -67,21 +68,21 @@ fun View.translateYAnimate(value: Float): Animator {
.apply { .apply {
duration = 300 duration = 300
doOnStart { doOnStart {
if (value == 0f) { show()
show()
}
} }
doOnEnd { doOnEnd {
if (value != 0f) { if (value != 0f) {
hide() hide()
} else {
show()
} }
} }
start() start()
} }
} }
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int) { fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator {
ObjectAnimator.ofInt(this, "peekHeight", value) return ObjectAnimator.ofInt(this, "peekHeight", value)
.apply { .apply {
duration = 300 duration = 300
start() start()

View file

@ -11,7 +11,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.4.0-beta02" def nav_version = "2.4.0-beta02"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath "com.diffplug.spotless:spotless-plugin-gradle:6.0.0" classpath "com.diffplug.spotless:spotless-plugin-gradle:6.0.1"
} }
} }