ui: fix more bottom sheet issues
Fix more bottom sheet issues regarding the queue sheet. Guess I brought it upon myself for nesting bottom sheets like this in a way that I doubt the behavior expects.
This commit is contained in:
parent
5536dd48df
commit
ed2f836280
1 changed files with 84 additions and 57 deletions
|
@ -19,7 +19,7 @@ package org.oxycblt.auxio
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.WindowInsets
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.view.isInvisible
|
||||
|
@ -27,7 +27,6 @@ import androidx.fragment.app.activityViewModels
|
|||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.NeoBottomSheetBehavior
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
@ -48,7 +47,8 @@ import org.oxycblt.auxio.util.*
|
|||
* high-level navigation features.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||
class MainFragment :
|
||||
ViewBindingFragment<FragmentMainBinding>(), ViewTreeObserver.OnPreDrawListener {
|
||||
private val playbackModel: PlaybackViewModel by androidActivityViewModels()
|
||||
private val navModel: NavigationViewModel by activityViewModels()
|
||||
private var callback: DynamicBackPressedCallback? = null
|
||||
|
@ -75,26 +75,14 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
|
||||
val playbackSheetBehavior =
|
||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||
|
||||
val queueSheetBehavior = binding.queueSheet.coordinatorLayoutBehavior as QueueSheetBehavior
|
||||
|
||||
queueSheetBehavior.addBottomSheetCallback(
|
||||
object : NeoBottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
||||
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
playbackSheetBehavior.isDraggable =
|
||||
!playbackSheetBehavior.isHideable &&
|
||||
newState == BottomSheetBehavior.STATE_COLLAPSED
|
||||
binding.handleWrapper.setOnClickListener {
|
||||
if (playbackSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED &&
|
||||
queueSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
queueSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
})
|
||||
|
||||
// We would use the onSlide callback, but doing that would require us to initialize
|
||||
// when the view first starts up, and that may not always work due to the insanity of
|
||||
// the CoordinatorLayout lifecycle. Instead, do the less efficient alternative of updating
|
||||
// the transition on every redraw.
|
||||
binding.playbackSheet.viewTreeObserver.addOnPreDrawListener {
|
||||
handleSheetTransitions()
|
||||
true
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
@ -104,6 +92,14 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
collectImmediately(playbackModel.song, ::updateSong)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
// Callback could still reasonably fire even if we clear the binding, attach/detach
|
||||
// our pre-draw listener our listener in onStart/onStop respectively.
|
||||
requireBinding().playbackSheet.viewTreeObserver.addOnPreDrawListener(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
callback?.isEnabled = true
|
||||
|
@ -114,6 +110,18 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
callback?.isEnabled = false
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
requireBinding().playbackSheet.viewTreeObserver.removeOnPreDrawListener(this)
|
||||
}
|
||||
|
||||
override fun onPreDraw(): Boolean {
|
||||
// CoordinatorLayout is insane and thus makes bottom sheet callbacks insane. Do our
|
||||
// checks before every draw.
|
||||
handleSheetTransitions()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun handleSheetTransitions() {
|
||||
val binding = requireBinding()
|
||||
val playbackSheetBehavior =
|
||||
|
@ -150,6 +158,10 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
}
|
||||
|
||||
binding.queueFragment.alpha = queueRatio
|
||||
|
||||
playbackSheetBehavior.isDraggable =
|
||||
!playbackSheetBehavior.isHideable &&
|
||||
queueSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED
|
||||
}
|
||||
|
||||
private fun handleMainNavigation(action: MainNavigationAction?) {
|
||||
|
@ -176,41 +188,6 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateSong(song: Song?) {
|
||||
val binding = requireBinding()
|
||||
val playbackSheetBehavior =
|
||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||
if (song != null) {
|
||||
playbackSheetBehavior.unsideSafe()
|
||||
} else {
|
||||
playbackSheetBehavior.hideSafe()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A back press callback that handles how to respond to backwards navigation in the detail
|
||||
* fragments and the playback panel.
|
||||
*
|
||||
* TODO: Migrate to new predictive API
|
||||
*/
|
||||
inner class DynamicBackPressedCallback : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
val binding = requireBinding()
|
||||
if (!tryCollapseAll()) {
|
||||
val navController = binding.exploreNavHost.findNavController()
|
||||
|
||||
if (navController.currentDestination?.id ==
|
||||
navController.graph.startDestinationId) {
|
||||
isEnabled = false
|
||||
requireActivity().onBackPressed()
|
||||
isEnabled = true
|
||||
} else {
|
||||
navController.navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryExpandAll(): Boolean {
|
||||
val binding = requireBinding()
|
||||
val playbackSheetBehavior =
|
||||
|
@ -244,4 +221,54 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun updateSong(song: Song?) {
|
||||
val binding = requireBinding()
|
||||
val playbackSheetBehavior =
|
||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||
if (song != null) {
|
||||
playbackSheetBehavior.unsideSafe()
|
||||
} else {
|
||||
playbackSheetBehavior.hideSafe()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A back press callback that handles how to respond to backwards navigation in the detail
|
||||
* fragments and the playback panel.
|
||||
*
|
||||
* TODO: Migrate to new predictive API
|
||||
*/
|
||||
inner class DynamicBackPressedCallback : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
val binding = requireBinding()
|
||||
|
||||
val queueSheetBehavior =
|
||||
binding.queueSheet.coordinatorLayoutBehavior as QueueSheetBehavior
|
||||
|
||||
if (queueSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
queueSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
return
|
||||
}
|
||||
|
||||
val playbackSheetBehavior =
|
||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||
|
||||
if (playbackSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED &&
|
||||
playbackSheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN) {
|
||||
playbackSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
return
|
||||
}
|
||||
|
||||
val navController = binding.exploreNavHost.findNavController()
|
||||
|
||||
if (navController.currentDestination?.id == navController.graph.startDestinationId) {
|
||||
isEnabled = false
|
||||
requireActivity().onBackPressed()
|
||||
isEnabled = true
|
||||
} else {
|
||||
navController.navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue