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:
parent
804db8b0d3
commit
7ef4eb5fde
14 changed files with 266 additions and 300 deletions
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -49,7 +49,7 @@ class GenreDetailFragment : DetailFragment() {
|
|||
}
|
||||
|
||||
val songAdapter = GenreSongAdapter(
|
||||
viewLifecycleOwner, detailModel,
|
||||
detailModel, viewLifecycleOwner,
|
||||
doOnClick = {
|
||||
playbackModel.playSong(it, PlaybackMode.IN_GENRE)
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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>
|
95
app/src/main/res/layout-land/item_artist_header.xml
Normal file
95
app/src/main/res/layout-land/item_artist_header.xml
Normal 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>
|
|
@ -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>
|
|
@ -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>
|
93
app/src/main/res/layout/item_artist_header.xml
Normal file
93
app/src/main/res/layout/item_artist_header.xml
Normal 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>
|
|
@ -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" />
|
||||
|
|
Loading…
Reference in a new issue