Add sorted genres/albums to LibraryFragment
Re-add the ability to show [sortable] Genres/Albums in LibraryFragment. Again.
This commit is contained in:
parent
08f8e50bbf
commit
8b0c2a7d2e
10 changed files with 133 additions and 131 deletions
|
|
@ -23,8 +23,6 @@ TODO:
|
||||||
|
|
||||||
/library/
|
/library/
|
||||||
|
|
||||||
- Re-add albums/genres into a single adapter
|
|
||||||
- Add highlighting to the current sortmode
|
|
||||||
- Search
|
- Search
|
||||||
- Exit functionality
|
- Exit functionality
|
||||||
- ? Show Artists, Albums, and Songs in search ?
|
- ? Show Artists, Albums, and Songs in search ?
|
||||||
|
|
|
||||||
110
app/src/main/java/org/oxycblt/auxio/library/LibraryAdapter.kt
Normal file
110
app/src/main/java/org/oxycblt/auxio/library/LibraryAdapter.kt
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
package org.oxycblt.auxio.library
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||||
|
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||||
|
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
||||||
|
import org.oxycblt.auxio.music.Album
|
||||||
|
import org.oxycblt.auxio.music.Artist
|
||||||
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
|
import org.oxycblt.auxio.music.Genre
|
||||||
|
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||||
|
import org.oxycblt.auxio.recycler.ClickListener
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_ALBUMS
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_GENRES
|
||||||
|
|
||||||
|
// A Great Value androidx ListAdapter that can display three types of ViewHolders.
|
||||||
|
class LibraryAdapter(
|
||||||
|
private val showMode: Int,
|
||||||
|
private val listener: ClickListener<BaseModel>
|
||||||
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
|
private var data: List<BaseModel>
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Assign the data on startup depending on the type
|
||||||
|
data = when (showMode) {
|
||||||
|
SHOW_GENRES -> listOf<Genre>()
|
||||||
|
SHOW_ALBUMS -> listOf<Album>()
|
||||||
|
SHOW_ARTISTS -> listOf<Artist>()
|
||||||
|
|
||||||
|
else -> listOf<Artist>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = data.size
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
// Return a different View Holder depending on the show type
|
||||||
|
return when (showMode) {
|
||||||
|
SHOW_GENRES -> GenreViewHolder(
|
||||||
|
ItemGenreBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
)
|
||||||
|
|
||||||
|
SHOW_ARTISTS -> ArtistViewHolder(
|
||||||
|
ItemArtistBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
)
|
||||||
|
|
||||||
|
SHOW_ALBUMS -> AlbumViewHolder(
|
||||||
|
ItemAlbumBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> ArtistViewHolder(
|
||||||
|
ItemArtistBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (showMode) {
|
||||||
|
SHOW_GENRES -> holder as GenreViewHolder
|
||||||
|
SHOW_ARTISTS -> holder as ArtistViewHolder
|
||||||
|
SHOW_ALBUMS -> holder as AlbumViewHolder
|
||||||
|
|
||||||
|
else -> return
|
||||||
|
}.bind(data[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the data, as its an internal value.
|
||||||
|
// TODO: Call this from a coroutine.
|
||||||
|
fun updateData(newData: List<BaseModel>) {
|
||||||
|
data = newData
|
||||||
|
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- VIEWHOLDERS ---
|
||||||
|
|
||||||
|
inner class GenreViewHolder(
|
||||||
|
private val binding: ItemGenreBinding
|
||||||
|
) : BaseViewHolder<BaseModel>(binding, listener) {
|
||||||
|
|
||||||
|
override fun onBind(model: BaseModel) {
|
||||||
|
binding.genre = model as Genre
|
||||||
|
binding.genreName.requestLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ArtistViewHolder(
|
||||||
|
private val binding: ItemArtistBinding
|
||||||
|
) : BaseViewHolder<BaseModel>(binding, listener) {
|
||||||
|
|
||||||
|
override fun onBind(model: BaseModel) {
|
||||||
|
binding.artist = model as Artist
|
||||||
|
binding.artistName.requestLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class AlbumViewHolder(
|
||||||
|
private val binding: ItemAlbumBinding
|
||||||
|
) : BaseViewHolder<BaseModel>(binding, listener) {
|
||||||
|
|
||||||
|
override fun onBind(model: BaseModel) {
|
||||||
|
binding.album = model as Album
|
||||||
|
binding.albumName.requestLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,13 +13,15 @@ import androidx.navigation.fragment.findNavController
|
||||||
import org.oxycblt.auxio.MainFragmentDirections
|
import org.oxycblt.auxio.MainFragmentDirections
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
||||||
import org.oxycblt.auxio.library.adapters.ArtistAdapter
|
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.music.Genre
|
import org.oxycblt.auxio.music.Genre
|
||||||
import org.oxycblt.auxio.music.MusicViewModel
|
import org.oxycblt.auxio.music.MusicViewModel
|
||||||
import org.oxycblt.auxio.recycler.ClickListener
|
import org.oxycblt.auxio.recycler.ClickListener
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_ALBUMS
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||||
|
import org.oxycblt.auxio.theme.SHOW_GENRES
|
||||||
import org.oxycblt.auxio.theme.applyColor
|
import org.oxycblt.auxio.theme.applyColor
|
||||||
import org.oxycblt.auxio.theme.applyDivider
|
import org.oxycblt.auxio.theme.applyDivider
|
||||||
import org.oxycblt.auxio.theme.resolveAttr
|
import org.oxycblt.auxio.theme.resolveAttr
|
||||||
|
|
@ -36,7 +38,8 @@ class LibraryFragment : Fragment() {
|
||||||
): View? {
|
): View? {
|
||||||
val binding = FragmentLibraryBinding.inflate(inflater)
|
val binding = FragmentLibraryBinding.inflate(inflater)
|
||||||
|
|
||||||
val artistAdapter = ArtistAdapter(
|
val artistAdapter = LibraryAdapter(
|
||||||
|
libraryModel.showMode.value!!,
|
||||||
ClickListener { navToItem(it) }
|
ClickListener { navToItem(it) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -49,9 +52,13 @@ class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
// Update the adapter with the new data
|
// Update the adapter with the new data
|
||||||
artistAdapter.updateData(
|
artistAdapter.updateData(
|
||||||
mode.getSortedArtistList(
|
when (libraryModel.showMode.value) {
|
||||||
musicModel.artists.value!!
|
SHOW_GENRES -> mode.getSortedGenreList(musicModel.genres.value!!)
|
||||||
)
|
SHOW_ARTISTS -> mode.getSortedArtistList(musicModel.artists.value!!)
|
||||||
|
SHOW_ALBUMS -> mode.getSortedAlbumList(musicModel.albums.value!!)
|
||||||
|
|
||||||
|
else -> mode.getSortedArtistList(musicModel.artists.value!!)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Then update the shown icon & the currently highlighted sort icon to reflect
|
// Then update the shown icon & the currently highlighted sort icon to reflect
|
||||||
|
|
@ -75,8 +82,6 @@ class LibraryFragment : Fragment() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.libraryToolbar.inflateMenu(R.menu.menu_library)
|
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Fragment created.")
|
Log.d(this::class.simpleName, "Fragment created.")
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
|
|
@ -93,6 +98,8 @@ class LibraryFragment : Fragment() {
|
||||||
if (!libraryModel.isAlreadyNavigating) {
|
if (!libraryModel.isAlreadyNavigating) {
|
||||||
libraryModel.isAlreadyNavigating = true
|
libraryModel.isAlreadyNavigating = true
|
||||||
|
|
||||||
|
Log.d(this::class.simpleName, "Navigating to the detail fragment for $baseModel.name")
|
||||||
|
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
when (baseModel) {
|
when (baseModel) {
|
||||||
is Genre -> MainFragmentDirections.actionShowGenre(baseModel.id)
|
is Genre -> MainFragmentDirections.actionShowGenre(baseModel.id)
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||||
class LibraryViewModel : ViewModel() {
|
class LibraryViewModel : ViewModel() {
|
||||||
var isAlreadyNavigating = false
|
var isAlreadyNavigating = false
|
||||||
|
|
||||||
// TODO: Move these to pref values when they're added
|
// TODO: Move these to prefs when they're added
|
||||||
private val mShowMode = MutableLiveData(SHOW_ARTISTS)
|
private val mShowMode = MutableLiveData(SHOW_ARTISTS)
|
||||||
val showMode: LiveData<Int> get() = mShowMode
|
val showMode: LiveData<Int> get() = mShowMode
|
||||||
|
|
||||||
private val mSortMode = MutableLiveData(SortMode.ALPHA_UP)
|
private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN)
|
||||||
val sortMode: LiveData<SortMode> get() = mSortMode
|
val sortMode: LiveData<SortMode> get() = mSortMode
|
||||||
|
|
||||||
fun updateSortMode(item: MenuItem) {
|
fun updateSortMode(item: MenuItem) {
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package org.oxycblt.auxio.library.adapters
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
|
||||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
|
||||||
import org.oxycblt.auxio.music.Album
|
|
||||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
|
||||||
import org.oxycblt.auxio.recycler.ClickListener
|
|
||||||
import org.oxycblt.auxio.recycler.DiffCallback
|
|
||||||
|
|
||||||
class AlbumAdapter(
|
|
||||||
private val listener: ClickListener<Album>
|
|
||||||
) : ListAdapter<Album, AlbumAdapter.ViewHolder>(DiffCallback()) {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(
|
|
||||||
ItemAlbumBinding.inflate(LayoutInflater.from(parent.context))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.bind(getItem(position))
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(
|
|
||||||
private val binding: ItemAlbumBinding
|
|
||||||
) : BaseViewHolder<Album>(binding, listener) {
|
|
||||||
|
|
||||||
override fun onBind(model: Album) {
|
|
||||||
binding.album = model
|
|
||||||
binding.albumName.requestLayout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
package org.oxycblt.auxio.library.adapters
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
|
||||||
import org.oxycblt.auxio.music.Artist
|
|
||||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
|
||||||
import org.oxycblt.auxio.recycler.ClickListener
|
|
||||||
|
|
||||||
class ArtistAdapter(
|
|
||||||
private val listener: ClickListener<Artist>
|
|
||||||
) : RecyclerView.Adapter<ArtistAdapter.ViewHolder>() {
|
|
||||||
|
|
||||||
private var data = listOf<Artist>()
|
|
||||||
|
|
||||||
override fun getItemCount(): Int = data.size
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(
|
|
||||||
ItemArtistBinding.inflate(LayoutInflater.from(parent.context))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.bind(data[position])
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateData(newData: List<Artist>) {
|
|
||||||
data = newData
|
|
||||||
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(
|
|
||||||
private val binding: ItemArtistBinding
|
|
||||||
) : BaseViewHolder<Artist>(binding, listener) {
|
|
||||||
|
|
||||||
override fun onBind(model: Artist) {
|
|
||||||
binding.artist = model
|
|
||||||
binding.artistName.requestLayout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package org.oxycblt.auxio.library.adapters
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
|
||||||
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
|
||||||
import org.oxycblt.auxio.music.Genre
|
|
||||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
|
||||||
import org.oxycblt.auxio.recycler.ClickListener
|
|
||||||
import org.oxycblt.auxio.recycler.DiffCallback
|
|
||||||
|
|
||||||
class GenreAdapter(
|
|
||||||
private val listener: ClickListener<Genre>
|
|
||||||
) : ListAdapter<Genre, GenreAdapter.ViewHolder>(DiffCallback()) {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(
|
|
||||||
ItemGenreBinding.inflate(LayoutInflater.from(parent.context))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.bind(getItem(position))
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(
|
|
||||||
private val binding: ItemGenreBinding
|
|
||||||
) : BaseViewHolder<Genre>(binding, listener) {
|
|
||||||
|
|
||||||
override fun onBind(model: Genre) {
|
|
||||||
binding.genre = model
|
|
||||||
binding.genreName.requestLayout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorPrimary">
|
android:tint="?attr/colorPrimary">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
|
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
android:background="?android:attr/windowBackground"
|
android:background="?android:attr/windowBackground"
|
||||||
android:elevation="@dimen/elevation_normal"
|
android:elevation="@dimen/elevation_normal"
|
||||||
app:popupTheme="@style/AppThemeOverlay.Popup"
|
app:popupTheme="@style/AppThemeOverlay.Popup"
|
||||||
|
app:menu="@menu/menu_library"
|
||||||
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
|
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
|
||||||
app:title="@string/title_library_fragment" />
|
app:title="@string/title_library_fragment" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@
|
||||||
android:id="@+id/sort_none"
|
android:id="@+id/sort_none"
|
||||||
android:icon="@drawable/ic_sort_none"
|
android:icon="@drawable/ic_sort_none"
|
||||||
android:title="@string/label_sort_none"
|
android:title="@string/label_sort_none"
|
||||||
android:contentDescription="@string/description_sort_none"/>
|
android:contentDescription="@string/description_sort_none" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/sort_alpha_down"
|
android:id="@+id/sort_alpha_down"
|
||||||
android:icon="@drawable/ic_sort_alpha_down"
|
android:icon="@drawable/ic_sort_alpha_down"
|
||||||
android:title="@string/label_sort_alpha_down"
|
android:title="@string/label_sort_alpha_down"
|
||||||
android:contentDescription="@string/description_sort_alpha_down"/>
|
android:contentDescription="@string/description_sort_alpha_down" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/sort_alpha_up"
|
android:id="@+id/sort_alpha_up"
|
||||||
android:icon="@drawable/ic_sort_alpha_up"
|
android:icon="@drawable/ic_sort_alpha_up"
|
||||||
android:title="@string/label_sort_alpha_up"
|
android:title="@string/label_sort_alpha_up"
|
||||||
android:contentDescription="@string/description_sort_alpha_up"/>
|
android:contentDescription="@string/description_sort_alpha_up" />
|
||||||
</menu>
|
</menu>
|
||||||
Loading…
Reference in a new issue