recycler: add selection adapter framework
Add a framework for selection-based adapters.
This commit is contained in:
parent
df6d80176d
commit
b891ee1fe6
15 changed files with 108 additions and 51 deletions
|
|
@ -30,7 +30,7 @@ import org.oxycblt.auxio.detail.DiscHeader
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||||
|
|
@ -173,7 +173,7 @@ class DiscHeaderViewHolder(private val binding: ItemDiscHeaderBinding) :
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AlbumSongViewHolder private constructor(private val binding: ItemAlbumSongBinding) :
|
private class AlbumSongViewHolder private constructor(private val binding: ItemAlbumSongBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
fun bind(item: Song, listener: MenuItemListener) {
|
fun bind(item: Song, listener: MenuItemListener) {
|
||||||
// Hide the track number view if the song does not have a track.
|
// Hide the track number view if the song does not have a track.
|
||||||
if (item.track != null) {
|
if (item.track != null) {
|
||||||
|
|
@ -196,7 +196,7 @@ private class AlbumSongViewHolder private constructor(private val binding: ItemA
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.songTrackBg.isPlaying = isPlaying
|
binding.songTrackBg.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||||
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.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||||
|
|
@ -154,7 +154,7 @@ private class ArtistDetailViewHolder private constructor(private val binding: It
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArtistAlbumViewHolder private constructor(private val binding: ItemParentBinding) :
|
private class ArtistAlbumViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
fun bind(item: Album, listener: MenuItemListener) {
|
fun bind(item: Album, listener: MenuItemListener) {
|
||||||
binding.parentImage.bind(item)
|
binding.parentImage.bind(item)
|
||||||
binding.parentName.text = item.resolveName(binding.context)
|
binding.parentName.text = item.resolveName(binding.context)
|
||||||
|
|
@ -164,7 +164,7 @@ private class ArtistAlbumViewHolder private constructor(private val binding: Ite
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.parentImage.isPlaying = isPlaying
|
binding.parentImage.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +184,7 @@ private class ArtistAlbumViewHolder private constructor(private val binding: Ite
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArtistSongViewHolder private constructor(private val binding: ItemSongBinding) :
|
private class ArtistSongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
fun bind(item: Song, listener: MenuItemListener) {
|
fun bind(item: Song, listener: MenuItemListener) {
|
||||||
binding.songAlbumCover.bind(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.text = item.resolveName(binding.context)
|
binding.songName.text = item.resolveName(binding.context)
|
||||||
|
|
@ -193,7 +193,7 @@ private class ArtistSongViewHolder private constructor(private val binding: Item
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.songAlbumCover.isPlaying = isPlaying
|
binding.songAlbumCover.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import org.oxycblt.auxio.detail.SortHeader
|
||||||
import org.oxycblt.auxio.ui.recycler.AuxioRecyclerView
|
import org.oxycblt.auxio.ui.recycler.AuxioRecyclerView
|
||||||
import org.oxycblt.auxio.ui.recycler.Header
|
import org.oxycblt.auxio.ui.recycler.Header
|
||||||
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||||
|
|
@ -39,7 +39,7 @@ import org.oxycblt.auxio.util.inflater
|
||||||
abstract class DetailAdapter<L : DetailAdapter.Listener>(
|
abstract class DetailAdapter<L : DetailAdapter.Listener>(
|
||||||
private val listener: L,
|
private val listener: L,
|
||||||
diffCallback: DiffUtil.ItemCallback<Item>
|
diffCallback: DiffUtil.ItemCallback<Item>
|
||||||
) : IndicatorAdapter<RecyclerView.ViewHolder>(), AuxioRecyclerView.SpanSizeLookup {
|
) : PlayingIndicatorAdapter<RecyclerView.ViewHolder>(), AuxioRecyclerView.SpanSizeLookup {
|
||||||
private var isPlaying = false
|
private var isPlaying = false
|
||||||
|
|
||||||
@Suppress("LeakingThis") override fun getItemCount() = differ.currentList.size
|
@Suppress("LeakingThis") override fun getItemCount() = differ.currentList.size
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import org.oxycblt.auxio.home.tabs.Tab
|
||||||
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.Genre
|
import org.oxycblt.auxio.music.Genre
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
import org.oxycblt.auxio.music.MusicMode
|
import org.oxycblt.auxio.music.MusicMode
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import org.oxycblt.auxio.music.Sort
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
import org.oxycblt.auxio.playback.secsToMs
|
import org.oxycblt.auxio.playback.secsToMs
|
||||||
import org.oxycblt.auxio.ui.recycler.AlbumViewHolder
|
import org.oxycblt.auxio.ui.recycler.AlbumViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||||
|
|
@ -117,7 +117,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AlbumAdapter(private val listener: MenuItemListener) :
|
private class AlbumAdapter(private val listener: MenuItemListener) :
|
||||||
IndicatorAdapter<AlbumViewHolder>() {
|
PlayingIndicatorAdapter<AlbumViewHolder>() {
|
||||||
private val differ = SyncListDiffer(this, AlbumViewHolder.DIFFER)
|
private val differ = SyncListDiffer(this, AlbumViewHolder.DIFFER)
|
||||||
|
|
||||||
override val currentList: List<Item>
|
override val currentList: List<Item>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Sort
|
import org.oxycblt.auxio.music.Sort
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
import org.oxycblt.auxio.ui.recycler.ArtistViewHolder
|
import org.oxycblt.auxio.ui.recycler.ArtistViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||||
|
|
@ -93,7 +93,7 @@ class ArtistListFragment : HomeListFragment<Artist>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArtistAdapter(private val listener: MenuItemListener) :
|
private class ArtistAdapter(private val listener: MenuItemListener) :
|
||||||
IndicatorAdapter<ArtistViewHolder>() {
|
PlayingIndicatorAdapter<ArtistViewHolder>() {
|
||||||
private val differ = SyncListDiffer(this, ArtistViewHolder.DIFFER)
|
private val differ = SyncListDiffer(this, ArtistViewHolder.DIFFER)
|
||||||
|
|
||||||
override val currentList: List<Item>
|
override val currentList: List<Item>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Sort
|
import org.oxycblt.auxio.music.Sort
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||||
|
|
@ -92,7 +92,7 @@ class GenreListFragment : HomeListFragment<Genre>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GenreAdapter(private val listener: MenuItemListener) :
|
private class GenreAdapter(private val listener: MenuItemListener) :
|
||||||
IndicatorAdapter<GenreViewHolder>() {
|
PlayingIndicatorAdapter<GenreViewHolder>() {
|
||||||
private val differ = SyncListDiffer(this, GenreViewHolder.DIFFER)
|
private val differ = SyncListDiffer(this, GenreViewHolder.DIFFER)
|
||||||
|
|
||||||
override val currentList: List<Item>
|
override val currentList: List<Item>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import org.oxycblt.auxio.music.Sort
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
import org.oxycblt.auxio.playback.secsToMs
|
import org.oxycblt.auxio.playback.secsToMs
|
||||||
import org.oxycblt.auxio.settings.Settings
|
import org.oxycblt.auxio.settings.Settings
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
||||||
|
|
@ -129,7 +129,7 @@ class SongListFragment : HomeListFragment<Song>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SongAdapter(private val listener: MenuItemListener) :
|
private class SongAdapter(private val listener: MenuItemListener) :
|
||||||
IndicatorAdapter<SongViewHolder>() {
|
PlayingIndicatorAdapter<SongViewHolder>() {
|
||||||
private val differ = SyncListDiffer(this, SongViewHolder.DIFFER)
|
private val differ = SyncListDiffer(this, SongViewHolder.DIFFER)
|
||||||
|
|
||||||
override val currentList: List<Item>
|
override val currentList: List<Item>
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ import org.oxycblt.auxio.util.getDimenSize
|
||||||
* Effectively a super-charged [StyledImageView].
|
* Effectively a super-charged [StyledImageView].
|
||||||
*
|
*
|
||||||
* This class enables the following features alongside the base features pf [StyledImageView]:
|
* This class enables the following features alongside the base features pf [StyledImageView]:
|
||||||
* - Activation indicator
|
* - Selection indicator
|
||||||
* - (Eventually) selection indicator
|
* - (Eventually) activation indicator
|
||||||
* - Support for ONE custom view
|
* - Support for ONE custom view
|
||||||
*
|
*
|
||||||
* This class is primarily intended for list items. For most uses, the simpler [StyledImageView] is
|
* This class is primarily intended for list items. For most uses, the simpler [StyledImageView] is
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
import org.oxycblt.auxio.ui.recycler.SyncListDiffer
|
||||||
import org.oxycblt.auxio.util.context
|
import org.oxycblt.auxio.util.context
|
||||||
|
|
@ -60,7 +60,7 @@ class QueueAdapter(private val listener: QueueItemListener) :
|
||||||
}
|
}
|
||||||
|
|
||||||
viewHolder.isEnabled = position > currentIndex
|
viewHolder.isEnabled = position > currentIndex
|
||||||
viewHolder.updateIndicator(position == currentIndex, isPlaying)
|
viewHolder.updatePlayingIndicator(position == currentIndex, isPlaying)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun submitList(newList: List<Song>) {
|
fun submitList(newList: List<Song>) {
|
||||||
|
|
@ -110,7 +110,7 @@ interface QueueItemListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
class QueueSongViewHolder private constructor(private val binding: ItemQueueSongBinding) :
|
class QueueSongViewHolder private constructor(private val binding: ItemQueueSongBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
val bodyView: View
|
val bodyView: View
|
||||||
get() = binding.body
|
get() = binding.body
|
||||||
val backgroundView: View
|
val backgroundView: View
|
||||||
|
|
@ -164,7 +164,7 @@ class QueueSongViewHolder private constructor(private val binding: ItemQueueSong
|
||||||
binding.songDragHandle.isEnabled = value
|
binding.songDragHandle.isEnabled = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.interactBody.isSelected = isActive
|
binding.interactBody.isSelected = isActive
|
||||||
binding.songAlbumCover.isPlaying = isPlaying
|
binding.songAlbumCover.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,14 @@ import org.oxycblt.auxio.ui.recycler.AuxioRecyclerView
|
||||||
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
import org.oxycblt.auxio.ui.recycler.GenreViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.Header
|
import org.oxycblt.auxio.ui.recycler.Header
|
||||||
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
import org.oxycblt.auxio.ui.recycler.HeaderViewHolder
|
||||||
import org.oxycblt.auxio.ui.recycler.IndicatorAdapter
|
import org.oxycblt.auxio.ui.recycler.PlayingIndicatorAdapter
|
||||||
import org.oxycblt.auxio.ui.recycler.Item
|
import org.oxycblt.auxio.ui.recycler.Item
|
||||||
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
import org.oxycblt.auxio.ui.recycler.MenuItemListener
|
||||||
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
import org.oxycblt.auxio.ui.recycler.SimpleItemCallback
|
||||||
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
import org.oxycblt.auxio.ui.recycler.SongViewHolder
|
||||||
|
|
||||||
class SearchAdapter(private val listener: MenuItemListener) :
|
class SearchAdapter(private val listener: MenuItemListener) :
|
||||||
IndicatorAdapter<RecyclerView.ViewHolder>(), AuxioRecyclerView.SpanSizeLookup {
|
PlayingIndicatorAdapter<RecyclerView.ViewHolder>(), AuxioRecyclerView.SpanSizeLookup {
|
||||||
private val differ = AsyncListDiffer(this, DIFFER)
|
private val differ = AsyncListDiffer(this, DIFFER)
|
||||||
|
|
||||||
override fun getItemCount() = differ.currentList.size
|
override fun getItemCount() = differ.currentList.size
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.oxycblt.auxio.ui.recycler
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
import org.oxycblt.auxio.util.logW
|
import org.oxycblt.auxio.util.logW
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -27,7 +28,7 @@ import org.oxycblt.auxio.util.logW
|
||||||
* itself.
|
* itself.
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class IndicatorAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {
|
abstract class PlayingIndicatorAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {
|
||||||
private var isPlaying = false
|
private var isPlaying = false
|
||||||
private var currentItem: Item? = null
|
private var currentItem: Item? = null
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@ abstract class IndicatorAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Ada
|
||||||
if (holder is ViewHolder) {
|
if (holder is ViewHolder) {
|
||||||
val item = currentList[position]
|
val item = currentList[position]
|
||||||
val currentItem = currentItem
|
val currentItem = currentItem
|
||||||
holder.updateIndicator(item == currentItem, isPlaying)
|
holder.updatePlayingIndicator(item == currentItem, isPlaying)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,20 +93,8 @@ abstract class IndicatorAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Ada
|
||||||
val PAYLOAD_INDICATOR_CHANGED = Any()
|
val PAYLOAD_INDICATOR_CHANGED = Any()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A ViewHolder that can respond to indicator updates. */
|
/** A ViewHolder that can respond to playing ]indicator updates. */
|
||||||
abstract class ViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
abstract class ViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
||||||
abstract fun updateIndicator(isActive: Boolean, isPlaying: Boolean)
|
abstract fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ViewHolder that correctly resizes the item to match the parent width, which it is not normally.
|
|
||||||
*/
|
|
||||||
abstract class DialogViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
|
||||||
init {
|
|
||||||
// Actually make the item full-width, which it won't be in dialogs
|
|
||||||
root.layoutParams =
|
|
||||||
RecyclerView.LayoutParams(
|
|
||||||
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.oxycblt.auxio.ui.recycler
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
|
|
@ -93,3 +94,16 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1)
|
manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHolder that correctly resizes the item to match the parent width, which it is not normally
|
||||||
|
* in dialogs.
|
||||||
|
*/
|
||||||
|
abstract class DialogViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
||||||
|
init {
|
||||||
|
// Actually make the item full-width, which it won't be in dialogs
|
||||||
|
root.layoutParams =
|
||||||
|
RecyclerView.LayoutParams(
|
||||||
|
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.oxycblt.auxio.ui.recycler
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter that implements selection indicators.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
|
abstract class SelectionIndicatorAdapter<VH : RecyclerView.ViewHolder> : PlayingIndicatorAdapter<VH>() {
|
||||||
|
private var selectedItems = setOf<Music>()
|
||||||
|
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: VH,
|
||||||
|
position: Int,
|
||||||
|
payloads: List<Any>
|
||||||
|
) {
|
||||||
|
super.onBindViewHolder(holder, position, payloads)
|
||||||
|
|
||||||
|
if (holder is ViewHolder) {
|
||||||
|
holder.updateSelectionIndicator(selectedItems.contains(currentList[position]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSelection(items: Set<Music>) {
|
||||||
|
val oldSelectedItems = selectedItems
|
||||||
|
|
||||||
|
if (items == oldSelectedItems) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedItems = items
|
||||||
|
for (i in currentList.indices) {
|
||||||
|
// TODO: Perhaps add an optimization that allows me to avoid the O(n) iteration
|
||||||
|
// assuming all list items are unique?
|
||||||
|
val item = currentList[i]
|
||||||
|
if (item !is Music) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldSelectedItems.contains(item) || items.contains(item)) {
|
||||||
|
notifyItemChanged(i, PAYLOAD_INDICATOR_CHANGED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A ViewHolder that can respond to selection indicator updates. */
|
||||||
|
abstract class ViewHolder(root: View) : RecyclerView.ViewHolder(root) {
|
||||||
|
abstract fun updateSelectionIndicator(isSelected: Boolean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ import org.oxycblt.auxio.util.inflater
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
fun bind(item: Song, listener: MenuItemListener) {
|
fun bind(item: Song, listener: MenuItemListener) {
|
||||||
binding.songAlbumCover.bind(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.text = item.resolveName(binding.context)
|
binding.songName.text = item.resolveName(binding.context)
|
||||||
|
|
@ -46,7 +46,7 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.songAlbumCover.isPlaying = isPlaying
|
binding.songAlbumCover.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class AlbumViewHolder private constructor(private val binding: ItemParentBinding) :
|
class AlbumViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(item: Album, listener: MenuItemListener) {
|
fun bind(item: Album, listener: MenuItemListener) {
|
||||||
binding.parentImage.bind(item)
|
binding.parentImage.bind(item)
|
||||||
|
|
@ -79,7 +79,7 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.parentImage.isPlaying = isPlaying
|
binding.parentImage.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class ArtistViewHolder private constructor(private val binding: ItemParentBinding) :
|
class ArtistViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(item: Artist, listener: MenuItemListener) {
|
fun bind(item: Artist, listener: MenuItemListener) {
|
||||||
binding.parentImage.bind(item)
|
binding.parentImage.bind(item)
|
||||||
|
|
@ -125,7 +125,7 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.parentImage.isPlaying = isPlaying
|
binding.parentImage.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class GenreViewHolder private constructor(private val binding: ItemParentBinding) :
|
class GenreViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||||
IndicatorAdapter.ViewHolder(binding.root) {
|
PlayingIndicatorAdapter.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(item: Genre, listener: MenuItemListener) {
|
fun bind(item: Genre, listener: MenuItemListener) {
|
||||||
binding.parentImage.bind(item)
|
binding.parentImage.bind(item)
|
||||||
|
|
@ -164,7 +164,7 @@ class GenreViewHolder private constructor(private val binding: ItemParentBinding
|
||||||
binding.root.setOnClickListener { listener.onItemClick(item) }
|
binding.root.setOnClickListener { listener.onItemClick(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIndicator(isActive: Boolean, isPlaying: Boolean) {
|
override fun updatePlayingIndicator(isActive: Boolean, isPlaying: Boolean) {
|
||||||
binding.root.isSelected = isActive
|
binding.root.isSelected = isActive
|
||||||
binding.parentImage.isPlaying = isPlaying
|
binding.parentImage.isPlaying = isPlaying
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue