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.
This commit is contained in:
OxygenCobalt 2021-10-20 20:11:07 -06:00
parent e01816a1dc
commit 9030de7774
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
5 changed files with 45 additions and 14 deletions

View file

@ -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)
}

View file

@ -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

View file

@ -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 ---

View file

@ -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)
}
}
}

View file

@ -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" />