Update ViewHolder structure

Make some minor improvements to the ViewHolder structure.
This commit is contained in:
OxygenCobalt 2020-10-24 12:32:05 -06:00
parent 55ed55c5dc
commit 32fe24e001
12 changed files with 60 additions and 63 deletions

View file

@ -61,7 +61,7 @@ dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0' implementation 'androidx.viewpager2:viewpager2:1.0.0'
// Navigation // Navigation
def navigation_version = "2.3.0" def navigation_version = "2.3.1"
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version" implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version" implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"

View file

@ -9,7 +9,7 @@ import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
class DetailAlbumAdapter( class DetailAlbumAdapter(
private val doOnClick: (Album) -> Unit private val doOnClick: (data: Album) -> Unit
) : ListAdapter<Album, DetailAlbumAdapter.ViewHolder>(DiffCallback()) { ) : ListAdapter<Album, DetailAlbumAdapter.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -27,8 +27,8 @@ class DetailAlbumAdapter(
private val binding: ItemArtistAlbumBinding, private val binding: ItemArtistAlbumBinding,
) : BaseViewHolder<Album>(binding, doOnClick) { ) : BaseViewHolder<Album>(binding, doOnClick) {
override fun onBind(model: Album) { override fun onBind(data: Album) {
binding.album = model binding.album = data
binding.albumName.requestLayout() binding.albumName.requestLayout()
} }

View file

@ -9,7 +9,7 @@ import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
class DetailArtistAdapter( class DetailArtistAdapter(
private val doOnClick: (Artist) -> Unit private val doOnClick: (data: Artist) -> Unit
) : ListAdapter<Artist, DetailArtistAdapter.ViewHolder>(DiffCallback()) { ) : ListAdapter<Artist, DetailArtistAdapter.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -27,8 +27,8 @@ class DetailArtistAdapter(
private val binding: ItemGenreArtistBinding private val binding: ItemGenreArtistBinding
) : BaseViewHolder<Artist>(binding, doOnClick) { ) : BaseViewHolder<Artist>(binding, doOnClick) {
override fun onBind(model: Artist) { override fun onBind(data: Artist) {
binding.artist = model binding.artist = data
binding.artistName.requestLayout() binding.artistName.requestLayout()
} }

View file

@ -2,24 +2,18 @@ package org.oxycblt.auxio.detail.adapters
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.DiffCallback import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.theme.accent
import org.oxycblt.auxio.theme.toColor
class DetailSongAdapter( class DetailSongAdapter(
private val doOnClick: (Song) -> Unit private val doOnClick: (data: Song) -> Unit
) : ListAdapter<Song, DetailSongAdapter.ViewHolder>(DiffCallback()) { ) : ListAdapter<Song, DetailSongAdapter.ViewHolder>(DiffCallback()) {
private var currentSong: Song? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder( return ViewHolder(
ItemAlbumSongBinding.inflate(LayoutInflater.from(parent.context)), ItemAlbumSongBinding.inflate(LayoutInflater.from(parent.context))
accent.first.toColor(parent.context)
) )
} }
@ -30,15 +24,10 @@ class DetailSongAdapter(
// Generic ViewHolder for a song // Generic ViewHolder for a song
inner class ViewHolder( inner class ViewHolder(
private val binding: ItemAlbumSongBinding, private val binding: ItemAlbumSongBinding,
@ColorInt private val resolvedAccent: Int
) : BaseViewHolder<Song>(binding, doOnClick) { ) : BaseViewHolder<Song>(binding, doOnClick) {
override fun onBind(model: Song) { override fun onBind(data: Song) {
binding.song = model binding.song = data
if (model == currentSong) {
binding.songName.setTextColor(resolvedAccent)
}
binding.songName.requestLayout() binding.songName.requestLayout()
} }

View file

@ -16,7 +16,7 @@ import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
// It cannot display multiple ViewHolders *at once* however. That's what SearchAdapter is for. // It cannot display multiple ViewHolders *at once* however. That's what SearchAdapter is for.
class LibraryAdapter( class LibraryAdapter(
private val showMode: ShowMode, private val showMode: ShowMode,
private val doOnClick: (BaseModel) -> Unit private val doOnClick: (data: BaseModel) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var data: List<BaseModel> private var data: List<BaseModel>

View file

@ -17,7 +17,7 @@ import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
class SearchAdapter( class SearchAdapter(
private val doOnClick: (BaseModel) -> Unit private val doOnClick: (data: BaseModel) -> Unit
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback<BaseModel>()) { ) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback<BaseModel>()) {
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {

View file

@ -15,7 +15,7 @@ import org.oxycblt.auxio.music.toDuration
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.Random.Default.nextLong import kotlin.random.Random.Default.nextLong
// TODO: Editing/Adding to Queue // TODO: Adding to Queue
// TODO: Add the playback service itself // TODO: Add the playback service itself
// TODO: Add loop control [From playback] // TODO: Add loop control [From playback]
// TODO: Implement persistence through Bundles [I want to keep my shuffles, okay?] // TODO: Implement persistence through Bundles [I want to keep my shuffles, okay?]

View file

@ -28,8 +28,12 @@ class QueueAdapter(
) : BaseViewHolder<Song>(binding, null) { ) : BaseViewHolder<Song>(binding, null) {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onBind(model: Song) { override fun onBind(data: Song) {
binding.song = model binding.song = data
binding.songName.requestLayout()
binding.songInfo.requestLayout()
binding.songDragHandle.setOnTouchListener { _, motionEvent -> binding.songDragHandle.setOnTouchListener { _, motionEvent ->
binding.songDragHandle.performClick() binding.songDragHandle.performClick()
@ -40,9 +44,6 @@ class QueueAdapter(
false false
} }
binding.songName.requestLayout()
binding.songInfo.requestLayout()
} }
} }
} }

View file

@ -7,7 +7,7 @@ import org.oxycblt.auxio.music.BaseModel
// ViewHolder abstraction that automates some of the things that are common for all ViewHolders. // ViewHolder abstraction that automates some of the things that are common for all ViewHolders.
abstract class BaseViewHolder<T : BaseModel>( abstract class BaseViewHolder<T : BaseModel>(
private val baseBinding: ViewDataBinding, private val baseBinding: ViewDataBinding,
private val doOnClick: ((T) -> Unit)? private val doOnClick: ((data: T) -> Unit)?
) : RecyclerView.ViewHolder(baseBinding.root) { ) : RecyclerView.ViewHolder(baseBinding.root) {
init { init {
// Force the layout to *actually* be the screen width // Force the layout to *actually* be the screen width
@ -16,15 +16,17 @@ abstract class BaseViewHolder<T : BaseModel>(
) )
} }
fun bind(model: T) { fun bind(data: T) {
doOnClick?.let { doOnClick?.let { onClick ->
baseBinding.root.setOnClickListener { it(model) } baseBinding.root.setOnClickListener {
onClick(data)
}
} }
onBind(model) onBind(data)
baseBinding.executePendingBindings() baseBinding.executePendingBindings()
} }
abstract fun onBind(model: T) protected abstract fun onBind(data: T)
} }

View file

@ -17,12 +17,12 @@ import org.oxycblt.auxio.music.Song
// All new instances should be created with from() instead of direct instantiation. // All new instances should be created with from() instead of direct instantiation.
class GenreViewHolder private constructor( class GenreViewHolder private constructor(
doOnClick: (Genre) -> Unit, private val binding: ItemGenreBinding,
private val binding: ItemGenreBinding doOnClick: (Genre) -> Unit
) : BaseViewHolder<Genre>(binding, doOnClick) { ) : BaseViewHolder<Genre>(binding, doOnClick) {
override fun onBind(model: Genre) { override fun onBind(data: Genre) {
binding.genre = model binding.genre = data
binding.genreName.requestLayout() binding.genreName.requestLayout()
} }
@ -31,20 +31,20 @@ class GenreViewHolder private constructor(
fun from(context: Context, doOnClick: (Genre) -> Unit): GenreViewHolder { fun from(context: Context, doOnClick: (Genre) -> Unit): GenreViewHolder {
return GenreViewHolder( return GenreViewHolder(
doOnClick, ItemGenreBinding.inflate(LayoutInflater.from(context)),
ItemGenreBinding.inflate(LayoutInflater.from(context)) doOnClick
) )
} }
} }
} }
class ArtistViewHolder private constructor( class ArtistViewHolder private constructor(
private val binding: ItemArtistBinding,
doOnClick: (Artist) -> Unit, doOnClick: (Artist) -> Unit,
private val binding: ItemArtistBinding
) : BaseViewHolder<Artist>(binding, doOnClick) { ) : BaseViewHolder<Artist>(binding, doOnClick) {
override fun onBind(model: Artist) { override fun onBind(data: Artist) {
binding.artist = model binding.artist = data
binding.artistName.requestLayout() binding.artistName.requestLayout()
} }
@ -53,30 +53,30 @@ class ArtistViewHolder private constructor(
fun from(context: Context, doOnClick: (Artist) -> Unit): ArtistViewHolder { fun from(context: Context, doOnClick: (Artist) -> Unit): ArtistViewHolder {
return ArtistViewHolder( return ArtistViewHolder(
doOnClick, ItemArtistBinding.inflate(LayoutInflater.from(context)),
ItemArtistBinding.inflate(LayoutInflater.from(context)) doOnClick
) )
} }
} }
} }
class AlbumViewHolder private constructor( class AlbumViewHolder private constructor(
doOnClick: (Album) -> Unit, private val binding: ItemAlbumBinding,
private val binding: ItemAlbumBinding doOnClick: (data: Album) -> Unit
) : BaseViewHolder<Album>(binding, doOnClick) { ) : BaseViewHolder<Album>(binding, doOnClick) {
override fun onBind(model: Album) { override fun onBind(data: Album) {
binding.album = model binding.album = data
binding.albumName.requestLayout() binding.albumName.requestLayout()
} }
companion object { companion object {
const val ITEM_TYPE = 12 const val ITEM_TYPE = 12
fun from(context: Context, doOnClick: (Album) -> Unit): AlbumViewHolder { fun from(context: Context, doOnClick: (data: Album) -> Unit): AlbumViewHolder {
return AlbumViewHolder( return AlbumViewHolder(
ItemAlbumBinding.inflate(LayoutInflater.from(context)),
doOnClick, doOnClick,
ItemAlbumBinding.inflate(LayoutInflater.from(context))
) )
} }
} }
@ -85,12 +85,12 @@ class AlbumViewHolder private constructor(
// TODO: Add indicators to song recycler items when they're being played? // TODO: Add indicators to song recycler items when they're being played?
class SongViewHolder private constructor( class SongViewHolder private constructor(
doOnClick: (Song) -> Unit, private val binding: ItemSongBinding,
private val binding: ItemSongBinding doOnClick: (data: Song) -> Unit,
) : BaseViewHolder<Song>(binding, doOnClick) { ) : BaseViewHolder<Song>(binding, doOnClick) {
override fun onBind(model: Song) { override fun onBind(data: Song) {
binding.song = model binding.song = data
binding.songName.requestLayout() binding.songName.requestLayout()
binding.songInfo.requestLayout() binding.songInfo.requestLayout()
@ -99,10 +99,13 @@ class SongViewHolder private constructor(
companion object { companion object {
const val ITEM_TYPE = 13 const val ITEM_TYPE = 13
fun from(context: Context, doOnClick: (Song) -> Unit): SongViewHolder { fun from(
context: Context,
doOnClick: (data: Song) -> Unit,
): SongViewHolder {
return SongViewHolder( return SongViewHolder(
doOnClick, ItemSongBinding.inflate(LayoutInflater.from(context)),
ItemSongBinding.inflate(LayoutInflater.from(context)) doOnClick
) )
} }
} }
@ -111,8 +114,9 @@ class SongViewHolder private constructor(
class HeaderViewHolder( class HeaderViewHolder(
private val binding: ItemHeaderBinding private val binding: ItemHeaderBinding
) : BaseViewHolder<Header>(binding, null) { ) : BaseViewHolder<Header>(binding, null) {
override fun onBind(model: Header) {
binding.header = model override fun onBind(data: Header) {
binding.header = data
} }
companion object { companion object {

View file

@ -7,7 +7,7 @@ import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
class SongAdapter( class SongAdapter(
private val data: List<Song>, private val data: List<Song>,
private val doOnClick: (Song) -> Unit private val doOnClick: (data: Song) -> Unit
) : RecyclerView.Adapter<SongViewHolder>() { ) : RecyclerView.Adapter<SongViewHolder>() {
override fun getItemCount(): Int = data.size override fun getItemCount(): Int = data.size

View file

@ -26,6 +26,7 @@
<string name="label_shuffle">Shuffle</string> <string name="label_shuffle">Shuffle</string>
<string name="label_play">Play</string> <string name="label_play">Play</string>
<string name="label_queue">Queue</string> <string name="label_queue">Queue</string>
<string name="label_queue_add">Add to queue</string>
<!-- Hint Namespace | EditText Hints --> <!-- Hint Namespace | EditText Hints -->
<string name="hint_search_library">Search Library…</string> <string name="hint_search_library">Search Library…</string>