From 97faa3f20ed1b921730ca8bddf54a9065d21cb7e Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 14 Oct 2024 18:25:20 -0600 Subject: [PATCH] detail: improve disc header design --- .../java/org/oxycblt/auxio/IntegerTable.kt | 4 +- .../oxycblt/auxio/detail/DetailViewModel.kt | 12 ++++- .../detail/list/AlbumDetailListAdapter.kt | 44 +++++++++++++++++ app/src/main/res/layout/item_disc_header.xml | 48 ++++++++----------- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt index eb1a27d53..3708fb92e 100644 --- a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt +++ b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt @@ -49,8 +49,10 @@ object IntegerTable { const val VIEW_TYPE_ARTIST_SONG = 0xA00A /** DiscHeaderViewHolder */ const val VIEW_TYPE_DISC_HEADER = 0xA00B + /** DiscHeaderViewHolder */ + const val VIEW_TYPE_DISC_DIVIDER = 0xA00C /** EditHeaderViewHolder */ - const val VIEW_TYPE_EDIT_HEADER = 0xA00C + const val VIEW_TYPE_EDIT_HEADER = 0xA00D /** PlaylistSongViewHolder */ const val VIEW_TYPE_PLAYLIST_SONG = 0xA00E /** "Music playback" notification code */ diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt index e125cb9f7..a2f502416 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -29,6 +29,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.yield import org.oxycblt.auxio.R +import org.oxycblt.auxio.detail.list.DiscDivider import org.oxycblt.auxio.detail.list.DiscHeader import org.oxycblt.auxio.detail.list.EditHeader import org.oxycblt.auxio.detail.list.SortHeader @@ -554,7 +555,16 @@ constructor( newList.add(Divider(header)) } newList.add(header) - section.discs.flatMap { listOf(DiscHeader(it.key)) + it.value } + buildList { + for (entry in section.discs) { + val discHeader = DiscHeader(inner = entry.key) + if (isNotEmpty()) { + add(DiscDivider(discHeader)) + } + add(discHeader) + addAll(entry.value) + } + } } } // Currently only the final section (songs, which can be sorted) are invalidatable diff --git a/app/src/main/java/org/oxycblt/auxio/detail/list/AlbumDetailListAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/list/AlbumDetailListAdapter.kt index c1134b207..2d09a1e4d 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/list/AlbumDetailListAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/list/AlbumDetailListAdapter.kt @@ -24,6 +24,7 @@ import androidx.core.view.isGone import androidx.core.view.isInvisible import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.divider.MaterialDivider import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.ItemAlbumSongBinding @@ -38,6 +39,7 @@ import org.oxycblt.auxio.music.info.Disc import org.oxycblt.auxio.music.info.resolveNumber import org.oxycblt.auxio.playback.formatDurationMs import org.oxycblt.auxio.util.context +import org.oxycblt.auxio.util.getAttrColorCompat import org.oxycblt.auxio.util.inflater /** @@ -52,6 +54,7 @@ class AlbumDetailListAdapter(private val listener: Listener) : when (getItem(position)) { // Support sub-headers for each disc, and special album songs. is DiscHeader -> DiscHeaderViewHolder.VIEW_TYPE + is DiscDivider -> DiscDividerViewHolder.VIEW_TYPE is Song -> AlbumSongViewHolder.VIEW_TYPE else -> super.getItemViewType(position) } @@ -59,6 +62,7 @@ class AlbumDetailListAdapter(private val listener: Listener) : override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { DiscHeaderViewHolder.VIEW_TYPE -> DiscHeaderViewHolder.from(parent) + DiscDividerViewHolder.VIEW_TYPE -> DiscDividerViewHolder.from(parent) AlbumSongViewHolder.VIEW_TYPE -> AlbumSongViewHolder.from(parent) else -> super.onCreateViewHolder(parent, viewType) } @@ -79,6 +83,8 @@ class AlbumDetailListAdapter(private val listener: Listener) : when { oldItem is Disc && newItem is Disc -> DiscHeaderViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem) + oldItem is DiscDivider && newItem is DiscDivider -> + DiscDividerViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem) oldItem is Song && newItem is Song -> AlbumSongViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem) @@ -96,6 +102,8 @@ class AlbumDetailListAdapter(private val listener: Listener) : */ data class DiscHeader(val inner: Disc?) : Item +data class DiscDivider(val anchor: DiscHeader?) : Item + /** * A [RecyclerView.ViewHolder] that displays a [DiscHeader] to delimit different disc groups. Use * [from] to create an instance. @@ -140,6 +148,42 @@ private class DiscHeaderViewHolder(private val binding: ItemDiscHeaderBinding) : } } +/** + * A [RecyclerView.ViewHolder] that displays a [DiscHeader]. Use [from] to create an instance. + * + * @author Alexander Capehart (OxygenCobalt) + */ +class DiscDividerViewHolder private constructor(divider: MaterialDivider) : + RecyclerView.ViewHolder(divider) { + + init { + divider.dividerColor = + divider.context + .getAttrColorCompat(com.google.android.material.R.attr.colorOutlineVariant) + .defaultColor + } + + companion object { + /** Unique ID for this ViewHolder type. */ + const val VIEW_TYPE = IntegerTable.VIEW_TYPE_DISC_DIVIDER + + /** + * Create a new instance. + * + * @param parent The parent to inflate this instance from. + * @return A new instance. + */ + fun from(parent: View) = DiscDividerViewHolder(MaterialDivider(parent.context)) + + /** A comparator that can be used with DiffUtil. */ + val DIFF_CALLBACK = + object : SimpleDiffCallback() { + override fun areContentsTheSame(oldItem: DiscDivider, newItem: DiscDivider) = + oldItem.anchor == newItem.anchor + } + } +} + /** * A [RecyclerView.ViewHolder] that displays a [Song] in the context of an [Album]. Use [from] to * create an instance. diff --git a/app/src/main/res/layout/item_disc_header.xml b/app/src/main/res/layout/item_disc_header.xml index dbcc0e4f6..cae2a6e0e 100644 --- a/app/src/main/res/layout/item_disc_header.xml +++ b/app/src/main/res/layout/item_disc_header.xml @@ -6,57 +6,49 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:paddingStart="@dimen/spacing_medium" - android:paddingTop="@dimen/spacing_mid_medium" + android:paddingTop="@dimen/spacing_small" android:paddingEnd="@dimen/spacing_medium" - android:paddingBottom="@dimen/spacing_mid_medium"> + android:paddingBottom="@dimen/spacing_small"> - - - - - + app:tint="@color/sel_on_cover_bg" + tools:ignore="ContentDescription" /> + tools:text="Part 1" />