From 9030de7774b9e50cb8062982382f70db9b8deba9 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Wed, 20 Oct 2021 20:11:07 -0600 Subject: [PATCH] ui: add edge-to-edge on bar-dependent fragments Add edge-to-edge on the Home, Detail, and Search fragments. This solution is not ideal at all, relying on viewModel state to make sure that the padding is only applied when the playback bar is not present. However, it works. I'll likely replace it with a better layout once I can figure out how similar layouts like Material Files' PersistentBarLyout work. --- .../oxycblt/auxio/detail/DetailFragment.kt | 3 ++ .../auxio/home/list/HomeListFragment.kt | 2 + .../oxycblt/auxio/search/SearchFragment.kt | 3 ++ .../java/org/oxycblt/auxio/util/ViewUtil.kt | 50 +++++++++++++------ app/src/main/res/layout/fragment_search.xml | 1 + 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt index 75434d813..81cc1129b 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt @@ -36,6 +36,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.SortMode import org.oxycblt.auxio.ui.memberBinding import org.oxycblt.auxio.util.applyEdge +import org.oxycblt.auxio.util.applyEdgeRespectingBar import org.oxycblt.auxio.util.isLandscape /** @@ -52,6 +53,8 @@ abstract class DetailFragment : Fragment() { binding.detailAppbar.updatePadding(top = bars.top) } + binding.detailRecycler.applyEdgeRespectingBar(playbackModel, viewLifecycleOwner) + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt index be1066b86..503ea6769 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt @@ -34,6 +34,7 @@ import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.memberBinding +import org.oxycblt.auxio.util.applyEdgeRespectingBar import org.oxycblt.auxio.util.applySpans import org.oxycblt.auxio.util.resolveDrawable @@ -73,6 +74,7 @@ abstract class HomeListFragment : Fragment() { adapter = homeAdapter setHasFixedSize(true) applySpans() + applyEdgeRespectingBar(playbackModel, viewLifecycleOwner) } // Make sure that this RecyclerView has data before startup diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index 0aa51c56c..a65ea1e0b 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -43,6 +43,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.newMenu import org.oxycblt.auxio.util.applyEdge +import org.oxycblt.auxio.util.applyEdgeRespectingBar import org.oxycblt.auxio.util.applySpans import org.oxycblt.auxio.util.getSystemServiceSafe import org.oxycblt.auxio.util.logD @@ -126,6 +127,8 @@ class SearchFragment : Fragment() { applySpans { pos -> searchAdapter.currentList[pos] is Header } + + applyEdgeRespectingBar(playbackModel, viewLifecycleOwner) } // --- VIEWMODEL SETUP --- diff --git a/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt index f0aa06c80..159d591a0 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt @@ -32,12 +32,14 @@ import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat +import androidx.core.view.updatePadding +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding -import com.google.android.material.appbar.AppBarLayout import com.google.android.material.shape.MaterialShapeDrawable import org.oxycblt.auxio.R +import org.oxycblt.auxio.playback.PlaybackViewModel /** * Apply a [MaterialShapeDrawable] to this view, automatically initializing the elevation overlay @@ -140,19 +142,6 @@ fun @receiver:AttrRes Int.resolveAttr(context: Context): Int { return color.resolveColor(context) } -/** - * Make this [AppBarLayout] fade a scrolling [view] out when it collapses. - * This is mostly because I am unable to figure out how to get a collapsing view not - * to draw under the status bar in edge-to-edge mode. - */ -fun AppBarLayout.makeScrollingViewFade(view: View) { - addOnOffsetChangedListener( - AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> - view.alpha = (view.height + verticalOffset) / view.height.toFloat() - } - ) -} - /** * Apply edge-to-edge tweaks to the root of a [ViewBinding]. * @param onApply What to do when the system bar insets are provided @@ -197,3 +186,36 @@ fun View.applyEdge(onApply: (Rect) -> Unit) { // Not on a version that supports edge-to-edge [yet], don't do anything } } + +/** + * Stopgap measure to make edge-to-edge work on views that also have a playback bar. + * The issue is that while we can apply padding initially, the padding will still be applied + * when the bar is shown, which is very ungood. We mitigate this by just checking the song state + * and removing the padding if it isnt available, which works okayish. I think Material Files has + * a better implementation of the same fix however, so once I'm able to hack that layout into + * Auxio things should be better. + */ +fun RecyclerView.applyEdgeRespectingBar( + playbackModel: PlaybackViewModel, + viewLifecycleOwner: LifecycleOwner +) { + var bottomPadding = 0 + + applyEdge { + bottomPadding = it.bottom + + if (playbackModel.song.value == null) { + updatePadding(bottom = bottomPadding) + } else { + updatePadding(bottom = 0) + } + } + + playbackModel.song.observe(viewLifecycleOwner) { song -> + if (song == null) { + updatePadding(bottom = bottomPadding) + } else { + updatePadding(bottom = 0) + } + } +} diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 77407d8b5..b5259763b 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -51,6 +51,7 @@ android:id="@+id/search_recycler" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipToPadding="false" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" tools:listitem="@layout/item_song" />