ui: redesign headers

Redesign the header component to be more aligned with M3 guidelines.

This includes moving the divider to the top when reasonable, using a
smaller font size, and using a tinted coloration to separate itself
from the list contents.
This commit is contained in:
Alexander Capehart 2023-01-16 19:35:16 -07:00
parent ad9d2f2d9e
commit fb93b82b2b
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
18 changed files with 55 additions and 45 deletions

View file

@ -28,8 +28,8 @@ import org.oxycblt.auxio.detail.SortHeader
import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.list.recycler.*
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.inflater

View file

@ -199,9 +199,7 @@ class HomeViewModel(application: Application) :
songsListInstructions = null
}
/**
* Signal that the specified [BasicInstructions] in [albumsListInstructions] were performed.
*/
/** Signal that the specified [BasicInstructions] in [albumsListInstructions] were performed. */
fun finishAlbumsListInstructions() {
albumsListInstructions = null
}
@ -213,9 +211,7 @@ class HomeViewModel(application: Application) :
artistsListInstructions = null
}
/**
* Signal that the specified [BasicInstructions] in [genresListInstructions] were performed.
*/
/** Signal that the specified [BasicInstructions] in [genresListInstructions] were performed. */
fun finishGenresListInstructions() {
genresListInstructions = null
}

View file

@ -31,9 +31,9 @@ import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView
import org.oxycblt.auxio.list.*
import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.recycler.AlbumViewHolder
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.list.recycler.ListDiffer
import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.music.*
import org.oxycblt.auxio.music.library.Sort
import org.oxycblt.auxio.playback.formatDurationMs

View file

@ -29,9 +29,9 @@ import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView
import org.oxycblt.auxio.list.*
import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.recycler.ArtistViewHolder
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.list.recycler.ListDiffer
import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode

View file

@ -28,10 +28,10 @@ import org.oxycblt.auxio.home.HomeViewModel
import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView
import org.oxycblt.auxio.list.*
import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.list.recycler.GenreViewHolder
import org.oxycblt.auxio.list.recycler.ListDiffer
import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode
@ -109,8 +109,7 @@ class GenreListFragment :
}
private fun updateList(artists: List<Genre>) {
genreAdapter.submitList(
artists, homeModel.genresListInstructions ?: BasicInstructions.DIFF)
genreAdapter.submitList(artists, homeModel.genresListInstructions ?: BasicInstructions.DIFF)
homeModel.finishGenresListInstructions()
}

View file

@ -30,10 +30,10 @@ import org.oxycblt.auxio.home.HomeViewModel
import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView
import org.oxycblt.auxio.list.*
import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.list.recycler.ListDiffer
import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter
import org.oxycblt.auxio.list.recycler.SongViewHolder
import org.oxycblt.auxio.list.recycler.BasicInstructions
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicMode
import org.oxycblt.auxio.music.MusicParent

View file

@ -25,5 +25,6 @@ interface Item
/**
* A "header" used for delimiting groups of data.
* @param titleRes The string resource used for the header's title.
* @param withDivider Whether to show a divider on the item.
*/
data class Header(@StringRes val titleRes: Int) : Item
data class Header(@StringRes val titleRes: Int, val withDivider: Boolean = true) : Item

View file

@ -99,11 +99,7 @@ enum class BasicInstructions {
}
private abstract class RealListDiffer<T>() : ListDiffer<T, BasicInstructions> {
override fun submitList(
newList: List<T>,
instructions: BasicInstructions,
onDone: () -> Unit
) {
override fun submitList(newList: List<T>, instructions: BasicInstructions, onDone: () -> Unit) {
when (instructions) {
BasicInstructions.DIFF -> diffList(newList, onDone)
BasicInstructions.REPLACE -> replaceList(newList, onDone)

View file

@ -18,6 +18,7 @@
package org.oxycblt.auxio.list.recycler
import android.view.View
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R
@ -249,6 +250,7 @@ class HeaderViewHolder private constructor(private val binding: ItemHeaderBindin
*/
fun bind(header: Header) {
binding.title.text = binding.context.getString(header.titleRes)
binding.headerDivider.isVisible = header.withDivider
}
companion object {

View file

@ -110,21 +110,21 @@ class SearchViewModel(application: Application) :
if (filterMode == null || filterMode == MusicMode.ARTISTS) {
library.artists.searchListImpl(query)?.let {
results.add(Header(R.string.lbl_artists))
results.add(Header(R.string.lbl_artists, withDivider = results.isNotEmpty()))
results.addAll(sort.artists(it))
}
}
if (filterMode == null || filterMode == MusicMode.ALBUMS) {
library.albums.searchListImpl(query)?.let {
results.add(Header(R.string.lbl_albums))
results.add(Header(R.string.lbl_albums, withDivider = results.isNotEmpty()))
results.addAll(sort.albums(it))
}
}
if (filterMode == null || filterMode == MusicMode.GENRES) {
library.genres.searchListImpl(query)?.let {
results.add(Header(R.string.lbl_genres))
results.add(Header(R.string.lbl_genres, withDivider = results.isNotEmpty()))
results.addAll(sort.genres(it))
}
}
@ -133,7 +133,7 @@ class SearchViewModel(application: Application) :
library.songs
.searchListImpl(query) { q, song -> song.path.name.contains(q) }
?.let {
results.add(Header(R.string.lbl_songs))
results.add(Header(R.string.lbl_songs, withDivider = results.isNotEmpty()))
results.addAll(sort.songs(it))
}
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/title"
style="@style/Widget.Auxio.TextView.Header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Songs" />

View file

@ -22,7 +22,11 @@
<TextView
android:id="@+id/disc_no"
style="@style/Widget.Auxio.TextView.Header"
android:paddingStart="@dimen/spacing_medium"
android:paddingEnd="@dimen/spacing_medium"
android:paddingTop="@dimen/spacing_mid_medium"
android:paddingBottom="@dimen/spacing_mid_medium"
android:textAppearance="@style/TextAppearance.Auxio.TitleMedium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"

View file

@ -6,6 +6,12 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:id="@+id/header_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@android:id/title"
style="@style/Widget.Auxio.TextView.Header"
@ -13,10 +19,4 @@
android:layout_height="wrap_content"
tools:text="Songs" />
<com.google.android.material.divider.MaterialDivider
android:id="@+id/header_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
</LinearLayout>

View file

@ -6,16 +6,21 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.divider.MaterialDivider
android:id="@+id/header_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/header_title"
style="@style/Widget.Auxio.TextView.Header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_mid_medium"
app:layout_constraintBottom_toTopOf="@id/header_divider"
app:layout_constraintEnd_toStartOf="@+id/header_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@+id/header_divider"
tools:text="Songs" />
<Button
@ -26,14 +31,8 @@
android:layout_marginEnd="@dimen/spacing_mid_medium"
android:contentDescription="@string/lbl_sort"
app:icon="@drawable/ic_sort_24"
app:layout_constraintBottom_toTopOf="@id/header_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@id/header_divider"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.divider.MaterialDivider
android:id="@+id/header_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -169,7 +169,8 @@
<item name="android:paddingEnd">@dimen/spacing_medium</item>
<item name="android:minHeight">@dimen/size_btn</item>
<item name="android:gravity">center_vertical</item>
<item name="android:textAppearance">@style/TextAppearance.Auxio.TitleMedium</item>
<item name="android:textColor">?attr/colorSecondary</item>
<item name="android:textAppearance">@style/TextAppearance.Auxio.LabelLarge</item>
</style>
<style name="Widget.Auxio.TextView.Detail" parent="Widget.Auxio.TextView.Base">
@ -196,7 +197,7 @@
<style name="Widget.Auxio.Button.Primary" parent="Widget.Material3.Button" />
<style name="Widget.Auxio.Button.Secondary" parent="Widget.Material3.Button.OutlinedButton" />
<style name="Widget.Auxio.Button.Secondary" parent="Widget.Material3.Button.TonalButton" />
<style name="Widget.Auxio.Button.Icon.Base" parent="Widget.Material3.Button.IconButton">
<item name="materialThemeOverlay">@style/ThemeOverlay.Auxio.UncheckableIconButton</item>

View file

@ -2,7 +2,8 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:title="@string/set_audio">
<PreferenceCategory android:title="@string/set_playback">
<PreferenceCategory android:title="@string/set_playback"
app:layout="@layout/item_bare_header">
<SwitchPreferenceCompat
app:key="@string/set_key_headset_autoplay"

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
app:title="@string/set_content">
<PreferenceCategory app:title="@string/set_music">
<PreferenceCategory app:title="@string/set_music"
app:layout="@layout/item_bare_header">
<SwitchPreferenceCompat
app:defaultValue="false"

View file

@ -3,7 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
app:title="@string/set_personalize">
<PreferenceCategory app:title="@string/set_display">
<PreferenceCategory app:title="@string/set_display"
app:layout="@layout/item_bare_header">
<org.oxycblt.auxio.settings.ui.WrappedDialogPreference
app:key="@string/set_key_home_tabs"