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.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.ViewTreeObserver
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
|
@ -27,7 +27,6 @@ import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.NeoBottomSheetBehavior
|
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
import com.google.android.material.transition.MaterialFadeThrough
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
@ -48,7 +47,8 @@ import org.oxycblt.auxio.util.*
|
||||||
* high-level navigation features.
|
* high-level navigation features.
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
class MainFragment :
|
||||||
|
ViewBindingFragment<FragmentMainBinding>(), ViewTreeObserver.OnPreDrawListener {
|
||||||
private val playbackModel: PlaybackViewModel by androidActivityViewModels()
|
private val playbackModel: PlaybackViewModel by androidActivityViewModels()
|
||||||
private val navModel: NavigationViewModel by activityViewModels()
|
private val navModel: NavigationViewModel by activityViewModels()
|
||||||
private var callback: DynamicBackPressedCallback? = null
|
private var callback: DynamicBackPressedCallback? = null
|
||||||
|
@ -75,26 +75,14 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||||
|
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||||
|
|
||||||
val queueSheetBehavior = binding.queueSheet.coordinatorLayoutBehavior as QueueSheetBehavior
|
val queueSheetBehavior = binding.queueSheet.coordinatorLayoutBehavior as QueueSheetBehavior
|
||||||
|
|
||||||
queueSheetBehavior.addBottomSheetCallback(
|
binding.handleWrapper.setOnClickListener {
|
||||||
object : NeoBottomSheetBehavior.BottomSheetCallback() {
|
if (playbackSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED &&
|
||||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
queueSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||||
|
queueSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
}
|
||||||
playbackSheetBehavior.isDraggable =
|
|
||||||
!playbackSheetBehavior.isHideable &&
|
|
||||||
newState == BottomSheetBehavior.STATE_COLLAPSED
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 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 ---
|
// --- VIEWMODEL SETUP ---
|
||||||
|
@ -104,6 +92,14 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||||
collectImmediately(playbackModel.song, ::updateSong)
|
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() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
callback?.isEnabled = true
|
callback?.isEnabled = true
|
||||||
|
@ -114,6 +110,18 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||||
callback?.isEnabled = false
|
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() {
|
private fun handleSheetTransitions() {
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
|
@ -150,11 +158,15 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.queueFragment.alpha = queueRatio
|
binding.queueFragment.alpha = queueRatio
|
||||||
|
|
||||||
|
playbackSheetBehavior.isDraggable =
|
||||||
|
!playbackSheetBehavior.isHideable &&
|
||||||
|
queueSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleMainNavigation(action: MainNavigationAction?) {
|
private fun handleMainNavigation(action: MainNavigationAction?) {
|
||||||
if (action == null) return
|
if (action == null) return
|
||||||
|
|
||||||
when (action) {
|
when (action) {
|
||||||
is MainNavigationAction.Expand -> tryExpandAll()
|
is MainNavigationAction.Expand -> tryExpandAll()
|
||||||
is MainNavigationAction.Collapse -> tryCollapseAll()
|
is MainNavigationAction.Collapse -> tryCollapseAll()
|
||||||
|
@ -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 {
|
private fun tryExpandAll(): Boolean {
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
|
@ -244,4 +221,54 @@ class MainFragment : ViewBindingFragment<FragmentMainBinding>() {
|
||||||
|
|
||||||
return false
|
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