home: add fast scroller
Add a new fast-scroller to the home view. This required some annoying hacks to work, but it seems to work pretty well.
This commit is contained in:
parent
7ef10fa4f8
commit
a253cfccc4
11 changed files with 131 additions and 26 deletions
|
@ -86,7 +86,7 @@ dependencies {
|
|||
|
||||
// Media
|
||||
// TODO: Migrate to media2 when I can figure out how to use it
|
||||
implementation "androidx.media:media:1.4.2"
|
||||
implementation "androidx.media:media:1.4.3"
|
||||
|
||||
// Preferences
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
|
@ -102,6 +102,8 @@ dependencies {
|
|||
// Material
|
||||
implementation "com.google.android.material:material:1.5.0-alpha04"
|
||||
|
||||
implementation 'me.zhanghai.android.fastscroll:library:1.1.7'
|
||||
|
||||
// --- DEBUG ---
|
||||
|
||||
// Lint
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.oxycblt.auxio.databinding.DialogAccentBinding
|
|||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.LifecycleDialog
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.resolveColor
|
||||
|
||||
/**
|
||||
* Dialog responsible for showing the list of accents to select.
|
||||
|
@ -55,13 +54,9 @@ class AccentDialog : LifecycleDialog() {
|
|||
binding.accentRecycler.apply {
|
||||
adapter = AccentAdapter(pendingAccent) { accent ->
|
||||
pendingAccent = accent
|
||||
|
||||
updateAccent()
|
||||
}
|
||||
}
|
||||
|
||||
updateAccent()
|
||||
|
||||
logD("Dialog created.")
|
||||
|
||||
return binding.root
|
||||
|
@ -90,15 +85,6 @@ class AccentDialog : LifecycleDialog() {
|
|||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
}
|
||||
|
||||
private fun updateAccent() {
|
||||
val accentColor = pendingAccent.color.resolveColor(requireContext())
|
||||
|
||||
(requireDialog() as AlertDialog).apply {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = BuildConfig.APPLICATION_ID + ".tag.ACCENT_PICKER"
|
||||
const val KEY_PENDING_ACCENT = BuildConfig.APPLICATION_ID + ".key.PENDING_ACCENT"
|
||||
|
|
|
@ -23,14 +23,17 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.iterator
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.core.view.updatePaddingRelative
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import org.oxycblt.auxio.MainFragmentDirections
|
||||
import org.oxycblt.auxio.R
|
||||
|
@ -46,10 +49,10 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.ui.memberBinding
|
||||
import org.oxycblt.auxio.util.applyEdge
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
import org.oxycblt.auxio.util.makeScrollingViewFade
|
||||
|
||||
/**
|
||||
* The main "Launching Point" fragment of Auxio, allowing navigation to the detail
|
||||
|
@ -63,6 +66,7 @@ import org.oxycblt.auxio.util.makeScrollingViewFade
|
|||
* @author OxygenCobalt
|
||||
*/
|
||||
class HomeFragment : Fragment() {
|
||||
private val binding: FragmentHomeBinding by memberBinding(FragmentHomeBinding::inflate)
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
|
@ -71,7 +75,6 @@ class HomeFragment : Fragment() {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val binding = FragmentHomeBinding.inflate(inflater)
|
||||
val sortItem: MenuItem
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
@ -82,7 +85,34 @@ class HomeFragment : Fragment() {
|
|||
binding.homeAppbar.updatePadding(top = bars.top)
|
||||
}
|
||||
|
||||
binding.homeAppbar.makeScrollingViewFade(binding.homeToolbar)
|
||||
binding.homeAppbar.apply {
|
||||
addOnOffsetChangedListener(
|
||||
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
|
||||
binding.homeToolbar.alpha = (binding.homeToolbar.height + verticalOffset) /
|
||||
binding.homeToolbar.height.toFloat()
|
||||
}
|
||||
)
|
||||
|
||||
post {
|
||||
// To add our fast scroller, we need to
|
||||
val vOffset = (
|
||||
(layoutParams as CoordinatorLayout.LayoutParams)
|
||||
.behavior as AppBarLayout.Behavior
|
||||
).topAndBottomOffset
|
||||
|
||||
binding.homePager.updatePaddingRelative(
|
||||
bottom = binding.homeAppbar.totalScrollRange + vOffset
|
||||
)
|
||||
|
||||
binding.homeAppbar.addOnOffsetChangedListener(
|
||||
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
|
||||
binding.homePager.updatePaddingRelative(
|
||||
bottom = binding.homeAppbar.totalScrollRange + verticalOffset
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.homeToolbar.apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
|
|
|
@ -23,11 +23,15 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.ui.AlbumViewHolder
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
|
||||
class AlbumListFragment : HomeListFragment() {
|
||||
override fun onCreateView(
|
||||
|
@ -51,6 +55,23 @@ class AlbumListFragment : HomeListFragment() {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
override val popupProvider: PopupTextProvider
|
||||
get() = PopupTextProvider { idx ->
|
||||
val album = homeModel.albums.value!![idx]
|
||||
|
||||
when (homeModel.getSortForDisplay(DisplayMode.SHOW_ALBUMS)) {
|
||||
SortMode.ASCENDING, SortMode.DESCENDING -> album.name.sliceArticle()
|
||||
.first().uppercase()
|
||||
|
||||
SortMode.ARTIST -> album.artist.name.sliceArticle()
|
||||
.first().uppercase()
|
||||
|
||||
SortMode.YEAR -> album.year.toString()
|
||||
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
class AlbumAdapter(
|
||||
private val doOnClick: (data: Album) -> Unit,
|
||||
private val doOnLongClick: (view: View, data: Album) -> Unit,
|
||||
|
|
|
@ -23,11 +23,13 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.ui.ArtistViewHolder
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
|
||||
class ArtistListFragment : HomeListFragment() {
|
||||
override fun onCreateView(
|
||||
|
@ -51,6 +53,11 @@ class ArtistListFragment : HomeListFragment() {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
override val popupProvider: PopupTextProvider
|
||||
get() = PopupTextProvider { idx ->
|
||||
homeModel.artists.value!![idx].name.sliceArticle().first().uppercase()
|
||||
}
|
||||
|
||||
class ArtistAdapter(
|
||||
private val doOnClick: (data: Artist) -> Unit,
|
||||
private val doOnLongClick: (view: View, data: Artist) -> Unit,
|
||||
|
|
|
@ -23,11 +23,13 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.ui.GenreViewHolder
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
|
||||
class GenreListFragment : HomeListFragment() {
|
||||
override fun onCreateView(
|
||||
|
@ -51,6 +53,11 @@ class GenreListFragment : HomeListFragment() {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
override val popupProvider: PopupTextProvider
|
||||
get() = PopupTextProvider { idx ->
|
||||
homeModel.genres.value!![idx].name.sliceArticle().first().uppercase()
|
||||
}
|
||||
|
||||
class GenreAdapter(
|
||||
private val doOnClick: (data: Genre) -> Unit,
|
||||
private val doOnLongClick: (view: View, data: Genre) -> Unit,
|
||||
|
|
|
@ -19,19 +19,25 @@
|
|||
package org.oxycblt.auxio.home.list
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentHomeListBinding
|
||||
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.applySpans
|
||||
import org.oxycblt.auxio.util.resolveDrawable
|
||||
|
||||
open class HomeListFragment : Fragment() {
|
||||
abstract class HomeListFragment : Fragment() {
|
||||
protected val binding: FragmentHomeListBinding by memberBinding(
|
||||
FragmentHomeListBinding::inflate
|
||||
)
|
||||
|
@ -39,6 +45,20 @@ open class HomeListFragment : Fragment() {
|
|||
protected val homeModel: HomeViewModel by activityViewModels()
|
||||
protected val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
abstract val popupProvider: PopupTextProvider
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.homeRecycler.apply {
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
.setPopupTextProvider(popupProvider)
|
||||
.setTrackDrawable(R.drawable.ui_scroll_track.resolveDrawable(context))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun <T : BaseModel, VH : RecyclerView.ViewHolder> setupRecycler(
|
||||
@IdRes uniqueId: Int,
|
||||
homeAdapter: HomeAdapter<T, VH>,
|
||||
|
|
|
@ -23,11 +23,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ItemPlayShuffleBinding
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SongViewHolder
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
import org.oxycblt.auxio.util.applySpans
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
|
||||
class SongListFragment : HomeListFragment() {
|
||||
|
@ -46,10 +51,33 @@ class SongListFragment : HomeListFragment() {
|
|||
)
|
||||
|
||||
setupRecycler(R.id.home_song_list, adapter, homeModel.songs)
|
||||
binding.homeRecycler.applySpans { it == 0 }
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override val popupProvider: PopupTextProvider
|
||||
get() = PopupTextProvider { idx ->
|
||||
if (idx == 0) {
|
||||
return@PopupTextProvider ""
|
||||
}
|
||||
|
||||
val song = homeModel.songs.value!![idx]
|
||||
|
||||
when (homeModel.getSortForDisplay(DisplayMode.SHOW_SONGS)) {
|
||||
SortMode.ASCENDING, SortMode.DESCENDING -> song.name.sliceArticle()
|
||||
.first().uppercase()
|
||||
|
||||
SortMode.ARTIST -> song.album.artist.name.sliceArticle()
|
||||
.first().uppercase()
|
||||
|
||||
SortMode.ALBUM -> song.album.name.sliceArticle()
|
||||
.first().uppercase()
|
||||
|
||||
SortMode.YEAR -> song.album.year.toString()
|
||||
}
|
||||
}
|
||||
|
||||
inner class SongsAdapter(
|
||||
private val doOnClick: (data: Song) -> Unit,
|
||||
private val doOnLongClick: (view: View, data: Song) -> Unit,
|
||||
|
|
|
@ -46,7 +46,6 @@ import org.oxycblt.auxio.util.applyEdge
|
|||
import org.oxycblt.auxio.util.applySpans
|
||||
import org.oxycblt.auxio.util.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.makeScrollingViewFade
|
||||
|
||||
/**
|
||||
* A [Fragment] that allows for the searching of the entire music library.
|
||||
|
@ -81,8 +80,6 @@ class SearchFragment : Fragment() {
|
|||
binding.searchAppbar.updatePadding(top = bars.top)
|
||||
}
|
||||
|
||||
binding.searchAppbar.makeScrollingViewFade(binding.searchToolbar)
|
||||
|
||||
binding.searchToolbar.apply {
|
||||
val itemId = when (searchModel.filterMode) {
|
||||
DisplayMode.SHOW_SONGS -> R.id.option_filter_songs
|
||||
|
|
7
app/src/main/res/drawable/ui_scroll_track.xml
Normal file
7
app/src/main/res/drawable/ui_scroll_track.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid
|
||||
android:color="@android:color/transparent" />
|
||||
|
||||
<size android:width="@dimen/spacing_small" />
|
||||
</shape>
|
|
@ -6,6 +6,7 @@
|
|||
<style name="Theme.Auxio.V27" parent="Theme.Auxio" />
|
||||
<!-- Android 12 configuration -->
|
||||
<style name="Theme.Auxio.V31" parent="Theme.Auxio.V27">
|
||||
<!-- Make sure to apply more accent-friendly values on older versions -->
|
||||
<item name="colorSecondary">?attr/colorPrimary</item>
|
||||
<item name="colorOnSecondary">?attr/colorOnPrimary</item>
|
||||
<item name="colorSecondaryContainer">?attr/colorPrimaryContainer</item>
|
||||
|
@ -21,9 +22,6 @@
|
|||
<item name="colorControlNormal">@color/control</item>
|
||||
<item name="colorControlHighlight">@color/overlay_selection</item>
|
||||
<item name="colorControlActivated">?attr/colorPrimary</item>
|
||||
|
||||
<item name="android:textColorHighlight">@color/overlay_text_highlight</item>
|
||||
<item name="android:textColorHighlightInverse">@color/overlay_text_highlight_inverse</item>
|
||||
</style>
|
||||
|
||||
<!-- Base theme -->
|
||||
|
@ -31,7 +29,9 @@
|
|||
<!-- Values -->
|
||||
<item name="colorOutline">@color/overlay_stroke</item>
|
||||
|
||||
<!-- Appearance -->
|
||||
<!-- Android component magic -->
|
||||
<item name="android:textColorHighlight">@color/overlay_text_highlight</item>
|
||||
<item name="android:textColorHighlightInverse">@color/overlay_text_highlight_inverse</item>
|
||||
<item name="android:colorBackground">?attr/colorSurface</item>
|
||||
<item name="android:windowBackground">?attr/colorSurface</item>
|
||||
<item name="android:fontFamily">@font/inter</item>
|
||||
|
|
Loading…
Reference in a new issue