Update artist detail layout

Update the artist detail layout so that it also relies on a recyclerview entirely instead of a nestedscrollview.
This commit is contained in:
OxygenCobalt 2020-12-28 13:55:20 -07:00
parent 804db8b0d3
commit 7ef4eb5fde
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
14 changed files with 266 additions and 300 deletions

View file

@ -108,7 +108,7 @@ class AlbumDetailFragment : DetailFragment() {
// Don't enable the sort button if there's only one song [or less]
if (detailModel.currentAlbum.value!!.songs.size < 2) {
binding.albumSortButton.disable(requireContext())
binding.albumSortButton.disable()
}
// If this fragment was created in order to nav to an item, then snap scroll to that item.

View file

@ -9,13 +9,13 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
import org.oxycblt.auxio.databinding.FragmentDetailBinding
import org.oxycblt.auxio.detail.adapters.ArtistAlbumAdapter
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.disable
import org.oxycblt.auxio.ui.setupAlbumActions
/**
@ -31,7 +31,7 @@ class ArtistDetailFragment : DetailFragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = FragmentArtistDetailBinding.inflate(inflater)
val binding = FragmentDetailBinding.inflate(inflater)
// If DetailViewModel isn't already storing the artist, get it from MusicStore
// using the ID given by the navigation arguments
@ -46,6 +46,7 @@ class ArtistDetailFragment : DetailFragment() {
}
val albumAdapter = ArtistAlbumAdapter(
detailModel, viewLifecycleOwner,
doOnClick = {
if (!detailModel.isNavigating) {
detailModel.updateNavigationStatus(true)
@ -65,11 +66,10 @@ class ArtistDetailFragment : DetailFragment() {
// --- UI SETUP ---
binding.lifecycleOwner = this
binding.detailModel = detailModel
binding.playbackModel = playbackModel
binding.artist = detailModel.currentArtist.value!!
binding.artistToolbar.apply {
binding.detailToolbar.apply {
inflateMenu(R.menu.menu_artist_detail)
setNavigationOnClickListener {
findNavController().navigateUp()
}
@ -98,12 +98,7 @@ class ArtistDetailFragment : DetailFragment() {
}
}
// Disable the sort button if there is only one album [Or less]
if (detailModel.currentArtist.value!!.albums.size < 2) {
binding.artistSortButton.disable(requireContext())
}
binding.artistAlbumRecycler.apply {
binding.detailRecycler.apply {
adapter = albumAdapter
setHasFixedSize(true)
}
@ -113,13 +108,11 @@ class ArtistDetailFragment : DetailFragment() {
detailModel.artistSortMode.observe(viewLifecycleOwner) { mode ->
logD("Updating sort mode to $mode")
// Update the current sort icon
binding.artistSortButton.setImageResource(mode.iconRes)
val data = mutableListOf<BaseModel>(detailModel.currentArtist.value!!).also {
it.addAll(mode.getSortedAlbumList(detailModel.currentArtist.value!!.albums))
}
// Then update the sort mode of the album adapter.
albumAdapter.submitList(
mode.getSortedAlbumList(detailModel.currentArtist.value!!.albums)
)
albumAdapter.submitList(data)
}
playbackModel.navToItem.observe(viewLifecycleOwner) {

View file

@ -49,7 +49,7 @@ class GenreDetailFragment : DetailFragment() {
}
val songAdapter = GenreSongAdapter(
viewLifecycleOwner, detailModel,
detailModel, viewLifecycleOwner,
doOnClick = {
playbackModel.playSong(it, PlaybackMode.IN_GENRE)
},

View file

@ -3,35 +3,76 @@ package org.oxycblt.auxio.detail.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
import org.oxycblt.auxio.databinding.ItemArtistHeaderBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.ui.disable
/**
* An adapter for displaying the [Album]s of an artist.
*/
class ArtistAlbumAdapter(
private val detailModel: DetailViewModel,
private val lifecycleOwner: LifecycleOwner,
private val doOnClick: (data: Album) -> Unit,
private val doOnLongClick: (data: Album, view: View) -> Unit,
) : ListAdapter<Album, RecyclerView.ViewHolder>(DiffCallback()) {
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) {
override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is Artist -> ARTIST_HEADER_ITEM_TYPE
is Album -> ARTIST_ALBUM_ITEM_TYPE
else -> -1
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return AlbumViewHolder(
ItemArtistAlbumBinding.inflate(LayoutInflater.from(parent.context))
)
return when (viewType) {
ARTIST_HEADER_ITEM_TYPE -> ArtistHeaderViewHolder(
ItemArtistHeaderBinding.inflate(LayoutInflater.from(parent.context))
)
ARTIST_ALBUM_ITEM_TYPE -> ArtistAlbumViewHolder(
ItemArtistAlbumBinding.inflate(LayoutInflater.from(parent.context))
)
else -> error("Invalid ViewHolder item type $viewType")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (val item = getItem(position)) {
is Album -> (holder as AlbumViewHolder).bind(item)
is Artist -> (holder as ArtistHeaderViewHolder).bind(item)
is Album -> (holder as ArtistAlbumViewHolder).bind(item)
}
}
inner class ArtistHeaderViewHolder(
private val binding: ItemArtistHeaderBinding
) : BaseViewHolder<Artist>(binding, null, null) {
override fun onBind(data: Artist) {
binding.artist = data
binding.detailModel = detailModel
binding.lifecycleOwner = lifecycleOwner
if (data.albums.size < 2) {
binding.artistSortButton.disable()
}
}
}
// Generic ViewHolder for a detail album
inner class AlbumViewHolder(
inner class ArtistAlbumViewHolder(
private val binding: ItemArtistAlbumBinding,
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick) {
@ -41,4 +82,9 @@ class ArtistAlbumAdapter(
binding.albumName.requestLayout()
}
}
companion object {
const val ARTIST_HEADER_ITEM_TYPE = 0xA022
const val ARTIST_ALBUM_ITEM_TYPE = 0xA023
}
}

View file

@ -14,13 +14,14 @@ import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.DiffCallback
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.ui.disable
/**
* An adapter for displaying the [Song]s of a genre.
*/
class GenreSongAdapter(
private val lifecycleOwner: LifecycleOwner,
private val detailModel: DetailViewModel,
private val lifecycleOwner: LifecycleOwner,
private val doOnClick: (data: Song) -> Unit,
private val doOnLongClick: (data: Song, view: View) -> Unit
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback()) {
@ -62,6 +63,10 @@ class GenreSongAdapter(
binding.genre = data
binding.detailModel = detailModel
binding.lifecycleOwner = lifecycleOwner
if (data.songs.size < 2) {
binding.genreSortButton.disable()
}
}
}

View file

@ -74,7 +74,7 @@ class LinearCenterScroller(target: Int) : RecyclerView.SmoothScroller() {
return calculateDeltaToFit(top, bottom, start, end)
}
private fun calcDyToMakeVisible(view: View): Int {
fun calcDyToMakeVisible(view: View): Int {
val manager = layoutManager ?: return 0
if (!manager.canScrollVertically()) return 0
@ -116,9 +116,7 @@ class LinearCenterScroller(target: Int) : RecyclerView.SmoothScroller() {
interimTargetDx = (TARGET_SEEK_SCROLL_DIST * scrollVector.x).toInt()
interimTargetDy = (TARGET_SEEK_SCROLL_DIST * scrollVector.y).toInt()
// To avoid UI hiccups, trigger a smooth scroll to a distance little further than the
// interim target. Since we track the distance travelled in onSeekTargetStep callback, it
// won't actually scroll more than what we need.
action.update(
(interimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO).toInt(),
(interimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO).toInt(),

View file

@ -37,9 +37,8 @@ fun MenuItem.applyColor(@ColorInt color: Int) {
/**
* Disable an image button.
* @param context [Context] required to change the [ImageButton]s color.
*/
fun ImageButton.disable(context: Context) {
fun ImageButton.disable() {
if (isEnabled) {
imageTintList = ColorStateList.valueOf(
R.color.inactive_color.toColor(context)
@ -240,7 +239,7 @@ fun PopupMenu.setupGenreActions(genre: Genre, playbackModel: PlaybackViewModel)
else -> false
}
}
inflateAndShow(R.menu.menu_genre_actions)
inflateAndShow(R.menu.menu_genre_detail)
}
/**

View file

@ -1,133 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".detail.ArtistDetailFragment">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/artist_toolbar"
style="@style/Toolbar.Style.Icon"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:menu="@menu/menu_artist_detail"
app:title="@string/label_library" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/artist_image"
android:layout_width="@dimen/size_cover_mid_huge"
android:layout_height="@dimen/size_cover_mid_huge"
android:layout_margin="@dimen/margin_medium"
android:contentDescription="@{@string/description_artist_image(artist.name)}"
app:artistImage="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/artist_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{artist.name}"
app:layout_constraintBottom_toTopOf="@+id/artist_genre"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Artist Name" />
<TextView
android:id="@+id/artist_genre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistGenre="@{artist}"
app:layout_constraintBottom_toTopOf="@+id/artist_counts"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="Genre Name" />
<TextView
android:id="@+id/artist_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistCounts="@{artist}"
app:layout_constraintBottom_toTopOf="@+id/artist_album_header"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<TextView
android:id="@+id/artist_album_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/label_albums"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_image" />
<ImageButton
android:id="@+id/artist_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
tools:src="@drawable/ic_sort_numeric_down" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/artist_album_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_album_header"
app:spanCount="2"
tools:itemCount="4"
tools:listitem="@layout/item_album" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</layout>

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/artist_image"
android:layout_width="@dimen/size_cover_mid_huge"
android:layout_height="@dimen/size_cover_mid_huge"
android:layout_margin="@dimen/margin_medium"
android:contentDescription="@{@string/description_artist_image(artist.name)}"
app:artistImage="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/artist_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{artist.name}"
app:layout_constraintBottom_toTopOf="@+id/artist_genre"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Artist Name" />
<TextView
android:id="@+id/artist_genre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistGenre="@{artist}"
app:layout_constraintBottom_toTopOf="@+id/artist_counts"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="Genre Name" />
<TextView
android:id="@+id/artist_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistCounts="@{artist}"
app:layout_constraintBottom_toTopOf="@+id/artist_album_header"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<TextView
android:id="@+id/artist_album_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/label_albums"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_image" />
<ImageButton
android:id="@+id/artist_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
app:sortIcon="@{detailModel.artistSortMode}"
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
tools:src="@drawable/ic_sort_numeric_down" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".detail.ArtistDetailFragment">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/artist_toolbar"
style="@style/Toolbar.Style.Icon"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:menu="@menu/menu_artist_detail"
app:title="@string/label_library" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/artist_image"
android:layout_width="@dimen/size_cover_huge"
android:layout_height="@dimen/size_cover_huge"
android:layout_marginTop="@dimen/margin_medium"
android:contentDescription="@{@string/description_artist_image(artist.name)}"
app:artistImage="@{artist}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/artist_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{artist.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_image"
tools:text="Artist Name" />
<TextView
android:id="@+id/artist_genre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistGenre="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="Genre Name" />
<TextView
android:id="@+id/artist_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistCounts="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<TextView
android:id="@+id/artist_album_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/label_albums"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
<ImageButton
android:id="@+id/artist_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
tools:src="@drawable/ic_sort_numeric_down" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/artist_album_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_album_header"
tools:itemCount="4"
tools:listitem="@layout/item_album" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</layout>

View file

@ -27,6 +27,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/genre_song_header"
tools:listitem="@layout/item_genre_header" />
tools:listitem="@layout/item_artist_header" />
</LinearLayout>
</layout>

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/artist_image"
android:layout_width="@dimen/size_cover_huge"
android:layout_height="@dimen/size_cover_huge"
android:layout_marginTop="@dimen/margin_medium"
android:contentDescription="@{@string/description_artist_image(artist.name)}"
app:artistImage="@{artist}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/artist_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{artist.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_image"
tools:text="Artist Name" />
<TextView
android:id="@+id/artist_genre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistGenre="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="Genre Name" />
<TextView
android:id="@+id/artist_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistCounts="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<TextView
android:id="@+id/artist_album_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/label_albums"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
<ImageButton
android:id="@+id/artist_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
app:sortIcon="@{detailModel.artistSortMode}"
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
tools:src="@drawable/ic_sort_numeric_down" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -35,7 +35,7 @@
android:id="@+id/artist_detail_fragment"
android:name="org.oxycblt.auxio.detail.ArtistDetailFragment"
android:label="ArtistDetailFragment"
tools:layout="@layout/fragment_artist_detail">
tools:layout="@layout/fragment_detail">
<argument
android:name="artistId"
app:argType="long" />