home: disable collapse when one tab
Disable the collapsing toolbar when there is only one tab. The TabLayout is hidden when there is one tab, so collapsing it does not make much sense.
This commit is contained in:
parent
4f3cb80a77
commit
304fccf0f9
8 changed files with 47 additions and 42 deletions
|
@ -22,6 +22,7 @@ at the cost of longer loading times
|
||||||
#### What's Improved
|
#### What's Improved
|
||||||
- Migrated to better-looking motion transitions
|
- Migrated to better-looking motion transitions
|
||||||
- App now exposes an (immutable) queue to the MediaSession
|
- App now exposes an (immutable) queue to the MediaSession
|
||||||
|
- Improved widget sizing/cover management
|
||||||
|
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
- Fixed default material theme being used before app shows up
|
- Fixed default material theme being used before app shows up
|
||||||
|
|
|
@ -67,7 +67,7 @@ class MainFragment :
|
||||||
.onBackPressedDispatcher.addCallback(
|
.onBackPressedDispatcher.addCallback(
|
||||||
viewLifecycleOwner, DynamicBackPressedCallback().also { callback = it })
|
viewLifecycleOwner, DynamicBackPressedCallback().also { callback = it })
|
||||||
|
|
||||||
binding.root.setOnApplyWindowInsetsListener { v, insets ->
|
binding.root.setOnApplyWindowInsetsListener { _, insets ->
|
||||||
lastInsets = insets
|
lastInsets = insets
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ class MainFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryExpandAll(): Boolean {
|
private fun tryExpandAll() {
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||||
|
@ -210,13 +210,10 @@ class MainFragment :
|
||||||
if (playbackSheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN &&
|
if (playbackSheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN &&
|
||||||
playbackSheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) {
|
playbackSheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
playbackSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
playbackSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
return true
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
private fun tryCollapseAll() {
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryCollapseAll(): Boolean {
|
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||||
|
@ -228,14 +225,10 @@ class MainFragment :
|
||||||
|
|
||||||
playbackSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
playbackSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
queueSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
queueSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
private fun tryUnhideAll() {
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryUnhideAll(): Boolean {
|
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||||
|
@ -248,14 +241,10 @@ class MainFragment :
|
||||||
playbackSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
playbackSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
|
||||||
queueSheetBehavior.isDraggable = true
|
queueSheetBehavior.isDraggable = true
|
||||||
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
private fun tryHideAll() {
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryHideAll(): Boolean {
|
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val playbackSheetBehavior =
|
val playbackSheetBehavior =
|
||||||
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackSheetBehavior
|
||||||
|
@ -269,11 +258,7 @@ class MainFragment :
|
||||||
|
|
||||||
playbackSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
playbackSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
||||||
queueSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
queueSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,6 +34,7 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
import com.google.android.material.transition.MaterialFadeThrough
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
@ -243,8 +244,19 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTabConfiguration() {
|
private fun updateTabConfiguration() {
|
||||||
|
val binding = requireBinding()
|
||||||
|
val toolbarParams = binding.homeToolbar.layoutParams as AppBarLayout.LayoutParams
|
||||||
if (homeModel.tabs.size == 1) {
|
if (homeModel.tabs.size == 1) {
|
||||||
requireBinding().homeTabs.isVisible = false
|
// A single tag makes the tab layout redundant, hide it and disable the collapsing
|
||||||
|
// behavior.
|
||||||
|
binding.homeTabs.isVisible = false
|
||||||
|
binding.homeAppbar.setExpanded(true, false)
|
||||||
|
toolbarParams.scrollFlags = 0
|
||||||
|
} else {
|
||||||
|
binding.homeTabs.isVisible = true
|
||||||
|
toolbarParams.scrollFlags =
|
||||||
|
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or
|
||||||
|
AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ import org.oxycblt.auxio.util.logD
|
||||||
/**
|
/**
|
||||||
* A [Fragment] that shows the queue and enables editing as well.
|
* A [Fragment] that shows the queue and enables editing as well.
|
||||||
*
|
*
|
||||||
* TODO: Test older versions
|
|
||||||
*
|
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemListener {
|
class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemListener {
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.oxycblt.auxio.util.logW
|
||||||
*/
|
*/
|
||||||
class SearchFragment :
|
class SearchFragment :
|
||||||
MenuFragment<FragmentSearchBinding>(), MenuItemListener, Toolbar.OnMenuItemClickListener {
|
MenuFragment<FragmentSearchBinding>(), MenuItemListener, Toolbar.OnMenuItemClickListener {
|
||||||
|
|
||||||
// SearchViewModel is only scoped to this Fragment
|
// SearchViewModel is only scoped to this Fragment
|
||||||
private val searchModel: SearchViewModel by androidViewModels()
|
private val searchModel: SearchViewModel by androidViewModels()
|
||||||
|
|
||||||
|
|
|
@ -253,9 +253,7 @@ val WindowInsets.systemBarInsetsCompat: Insets
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
|
||||||
getInsets(WindowInsets.Type.systemBars())
|
getInsets(WindowInsets.Type.systemBars())
|
||||||
}
|
}
|
||||||
else -> {
|
else -> systemWindowInsetsCompat
|
||||||
@Suppress("DEPRECATION") systemWindowInsets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,11 +275,20 @@ val WindowInsets.systemGestureInsetsCompat: Insets
|
||||||
getInsets(WindowInsets.Type.systemBars()))
|
getInsets(WindowInsets.Type.systemBars()))
|
||||||
}
|
}
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
|
||||||
@Suppress("DEPRECATION") Insets.max(systemGestureInsets, systemWindowInsets)
|
@Suppress("DEPRECATION") Insets.max(systemGestureInsets, systemBarInsetsCompat)
|
||||||
}
|
}
|
||||||
else -> Insets.of(0, 0, 0, 0)
|
else -> systemWindowInsetsCompat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
val WindowInsets.systemWindowInsetsCompat: Insets
|
||||||
|
get() =
|
||||||
|
Insets.of(
|
||||||
|
systemWindowInsetLeft,
|
||||||
|
systemWindowInsetTop,
|
||||||
|
systemWindowInsetRight,
|
||||||
|
systemWindowInsetBottom)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the system bar insets in a version-aware manner. This can be used to modify the insets
|
* Replaces the system bar insets in a version-aware manner. This can be used to modify the insets
|
||||||
* for child views in a way that follows all of the frustrating changes that were made between 8-11.
|
* for child views in a way that follows all of the frustrating changes that were made between 8-11.
|
||||||
|
|
|
@ -94,27 +94,28 @@ class WidgetComponent(private val context: Context) :
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the image in a such a way that we don't hit the RemoteView size
|
// We resize the image in a such a way that we don't hit the RemoteView size
|
||||||
// limit, which is the size of an RGB_8888 bitmap 1.5x the screen size. Note
|
// limit, which is the size of an RGB_8888 bitmap 1.5x the screen size. When
|
||||||
// that we actually set the limit to be half the memory limit so that it's
|
// enabling rounded corners, we further reduce it by a factor of 8 to get 16-dp
|
||||||
// less likely for us to hit it. it to really ensure we don't hit the limit.
|
// rounded corners, whereas we only downsize it by 2 when there is rounded
|
||||||
// This also creates the consistent sizes required for round bitmaps.
|
// corners just to ensure that we do not hit the memory limit.
|
||||||
val metrics = context.resources.displayMetrics
|
val metrics = context.resources.displayMetrics
|
||||||
val sw = metrics.widthPixels
|
val sw = metrics.widthPixels
|
||||||
val sh = metrics.heightPixels
|
val sh = metrics.heightPixels
|
||||||
builder.size((sqrt((6f * sw * sh) / 8f)).toInt())
|
|
||||||
|
|
||||||
return if (cornerRadius > 0) {
|
return if (cornerRadius > 0) {
|
||||||
this@WidgetComponent.logD("Loading round covers: $cornerRadius")
|
this@WidgetComponent.logD("Loading round covers: $cornerRadius")
|
||||||
|
|
||||||
// Use RoundedCornersTransformation. This is because our hack to get a 1:1
|
builder
|
||||||
// aspect ratio on widget ImageViews doesn't actually result in a square
|
.size(sqrt((6f / 4f / 8f) * sw * sh).toInt())
|
||||||
// ImageView, so clipToOutline won't work.
|
.transformations(
|
||||||
builder.transformations(
|
|
||||||
SquareFrameTransform.INSTANCE,
|
SquareFrameTransform.INSTANCE,
|
||||||
|
// RoundedCornersTransformation is used instead of clipToOutline
|
||||||
|
// since our hack to get a 1:1 cover on the widget actually does
|
||||||
|
// not result in a square view, making clipToOutline not work.
|
||||||
RoundedCornersTransformation(cornerRadius.toFloat()))
|
RoundedCornersTransformation(cornerRadius.toFloat()))
|
||||||
} else {
|
} else {
|
||||||
builder
|
builder.size(sqrt((6f / 4f / 2f) * sw * sh).toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,6 @@
|
||||||
<dimen name="recycler_fab_space_normal">88dp</dimen>
|
<dimen name="recycler_fab_space_normal">88dp</dimen>
|
||||||
<dimen name="recycler_fab_space_large">128dp</dimen>
|
<dimen name="recycler_fab_space_large">128dp</dimen>
|
||||||
|
|
||||||
<dimen name="widget_width_def">176dp</dimen>
|
<dimen name="widget_width_def">180dp</dimen>
|
||||||
<dimen name="widget_height_def">100dp</dimen>
|
<dimen name="widget_height_def">100dp</dimen>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue