Move detail controls to Toolbar

Move the play/shuffle buttons from the header of the DetailFragments to their Toolbar, it makes far more sense for them to be there honestly.
This commit is contained in:
OxygenCobalt 2020-10-18 15:13:03 -06:00
parent d01aa3ea4a
commit c4c115274b
27 changed files with 147 additions and 192 deletions

View file

@ -55,16 +55,30 @@ class AlbumDetailFragment : Fragment() {
binding.playbackModel = playbackModel
binding.album = detailModel.currentAlbum.value!!
binding.albumToolbar.apply {
setNavigationOnClickListener {
findNavController().navigateUp()
}
setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_shuffle -> playbackModel.play(
detailModel.currentAlbum.value!!,
true
)
R.id.action_play -> playbackModel.play(detailModel.currentAlbum.value!!, false)
}
true
}
}
binding.albumSongRecycler.apply {
adapter = songAdapter
applyDivider()
setHasFixedSize(true)
}
binding.albumToolbar.setNavigationOnClickListener {
findNavController().navigateUp()
}
// Don't enable the sort button if there's only one song [or less]
if (detailModel.currentAlbum.value!!.numSongs < 2) {
binding.albumSortButton.disable(requireContext())
@ -84,16 +98,6 @@ class AlbumDetailFragment : Fragment() {
)
}
// Observe playback model to update the play button
// TODO: Make these icons animated
playbackModel.currentMode.observe(viewLifecycleOwner) {
updatePlayButton(it, binding)
}
playbackModel.isPlaying.observe(viewLifecycleOwner) {
updatePlayButton(playbackModel.currentMode.value!!, binding)
}
// If the album was shown directly from LibraryFragment, Then enable the ability to
// navigate upwards to the parent artist
if (args.enableParentNav) {
@ -118,34 +122,4 @@ class AlbumDetailFragment : Fragment() {
return binding.root
}
// Update the play button depending on the current playback status
// If playing this album -> Make button show media controls
// If not playing this album -> Make button update playback to the artist
private fun updatePlayButton(
mode: PlaybackMode,
binding: FragmentAlbumDetailBinding
) {
playbackModel.currentParent.value?.let { parent ->
if (mode == PlaybackMode.IN_ALBUM &&
parent.id == detailModel.currentAlbum.value!!.id
) {
if (playbackModel.isPlaying.value!!) {
binding.albumPlay.setImageResource(R.drawable.ic_pause)
} else {
binding.albumPlay.setImageResource(R.drawable.ic_play)
}
binding.albumPlay.setOnClickListener {
playbackModel.invertPlayingStatus()
}
} else {
binding.albumPlay.setImageResource(R.drawable.ic_play)
binding.albumPlay.setOnClickListener {
playbackModel.play(detailModel.currentAlbum.value!!, false)
}
}
}
}
}

View file

@ -13,13 +13,11 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackMode
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.theme.applyDivider
import org.oxycblt.auxio.theme.disable
class ArtistDetailFragment : Fragment() {
private val args: ArtistDetailFragmentArgs by navArgs()
private val detailModel: DetailViewModel by activityViewModels()
private val playbackModel: PlaybackViewModel by activityViewModels()
@ -60,8 +58,22 @@ class ArtistDetailFragment : Fragment() {
binding.playbackModel = playbackModel
binding.artist = detailModel.currentArtist.value!!
binding.artistToolbar.setNavigationOnClickListener {
findNavController().navigateUp()
binding.artistToolbar.apply {
setNavigationOnClickListener {
findNavController().navigateUp()
}
setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_shuffle -> playbackModel.play(
detailModel.currentArtist.value!!,
true
)
R.id.action_play -> playbackModel.play(detailModel.currentArtist.value!!, false)
}
true
}
}
// Disable the sort button if there is only one album [Or less]
@ -89,49 +101,11 @@ class ArtistDetailFragment : Fragment() {
)
}
playbackModel.currentMode.observe(viewLifecycleOwner) {
updatePlayButton(it, binding)
}
playbackModel.isPlaying.observe(viewLifecycleOwner) {
updatePlayButton(playbackModel.currentMode.value!!, binding)
}
Log.d(this::class.simpleName, "Fragment created.")
return binding.root
}
// Update the play button depending on the current playback status
// If playing this artist -> Make button show media controls
// If not playing this artist -> Make button update playback to the artist
private fun updatePlayButton(
mode: PlaybackMode,
binding: FragmentArtistDetailBinding
) {
playbackModel.currentParent.value?.let { parent ->
if (mode == PlaybackMode.IN_ARTIST &&
parent.id == detailModel.currentArtist.value!!.id
) {
if (playbackModel.isPlaying.value!!) {
binding.artistPlay.setImageResource(R.drawable.ic_pause)
} else {
binding.artistPlay.setImageResource(R.drawable.ic_play)
}
binding.artistPlay.setOnClickListener {
playbackModel.invertPlayingStatus()
}
} else {
binding.artistPlay.setImageResource(R.drawable.ic_play)
binding.artistPlay.setOnClickListener {
playbackModel.play(detailModel.currentAlbum.value!!, false)
}
}
}
}
override fun onResume() {
super.onResume()

View file

@ -10,8 +10,8 @@ import org.oxycblt.auxio.recycler.SortMode
// ViewModel for the Detail Fragments.
// TODO:
// - Implement a system where the Toolbar will update with the info [And Media Controls] when
// the main info of the detail fragment is removed.
// - Implement a system where the Toolbar will update with some infowhen
// the main detail header is obscured.
class DetailViewModel : ViewModel() {
private var mIsNavigating = false
val isNavigating: Boolean get() = mIsNavigating

View file

@ -9,9 +9,11 @@ import androidx.fragment.app.Fragment
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.FragmentGenreDetailBinding
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.theme.applyDivider
import org.oxycblt.auxio.theme.disable
@ -19,6 +21,7 @@ class GenreDetailFragment : Fragment() {
private val args: GenreDetailFragmentArgs by navArgs()
private val detailModel: DetailViewModel by activityViewModels()
private val playbackModel: PlaybackViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
@ -55,8 +58,22 @@ class GenreDetailFragment : Fragment() {
binding.detailModel = detailModel
binding.genre = detailModel.currentGenre.value
binding.genreToolbar.setNavigationOnClickListener {
findNavController().navigateUp()
binding.genreToolbar.apply {
setNavigationOnClickListener {
findNavController().navigateUp()
}
setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_shuffle -> playbackModel.play(
detailModel.currentGenre.value!!,
true
)
R.id.action_play -> playbackModel.play(detailModel.currentGenre.value!!, false)
}
true
}
}
// Disable the sort button if there is only one artist [Or less]

View file

@ -21,7 +21,7 @@ class LibraryViewModel : ViewModel() {
val searchHasFocus: Boolean get() = mSearchHasFocus
// TODO: Move these to prefs when they're added
private val mShowMode = MutableLiveData(ShowMode.SHOW_ARTISTS)
private val mShowMode = MutableLiveData(ShowMode.SHOW_GENRES)
val showMode: LiveData<ShowMode> get() = mShowMode
private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN)

View file

@ -38,7 +38,7 @@ class CompactPlaybackFragment : Fragment() {
binding.lifecycleOwner = viewLifecycleOwner
// Put a placeholder song in the binding & hide the playback fragment initially,
// as for some reason the attach event doesn't register anymore w/LiveData
// just in case.
binding.song = MusicStore.getInstance().songs[0]
binding.playbackModel = playbackModel
@ -59,7 +59,6 @@ class CompactPlaybackFragment : Fragment() {
}
}
// TODO: Fix the thing where the icons will animate on startup
playbackModel.isPlaying.observe(viewLifecycleOwner) {
if (playbackModel.canAnimate) {
if (it) {

View file

@ -46,7 +46,9 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
// --- UI SETUP ---
binding.lifecycleOwner = viewLifecycleOwner
binding.playbackModel = playbackModel
binding.song = playbackModel.currentSong.value!!
binding.playbackToolbar.setNavigationOnClickListener {
findNavController().navigateUp()
@ -54,7 +56,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
// Make marquee scroll work
binding.playbackSong.isSelected = true
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
// --- VIEWMODEL SETUP --

View file

@ -5,5 +5,5 @@ package org.oxycblt.auxio.playback
// IN_ARTIST -> Play from the songs of the artist
// IN_ALBUM -> Play from the songs of the album
enum class PlaybackMode {
IN_ARTIST, IN_ALBUM, ALL_SONGS;
IN_ARTIST, IN_GENRE, IN_ALBUM, ALL_SONGS;
}

View file

@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.toDuration
@ -63,6 +64,15 @@ class PlaybackViewModel : ViewModel() {
// Update the current song while changing the queue mode.
fun update(song: Song, mode: PlaybackMode) {
// Auxio doesn't support playing songs while swapping the mode to GENRE, as genres
// are bound to artists, not songs.
if (mode == PlaybackMode.IN_GENRE) {
Log.e(this::class.simpleName, "Auxio cant play songs with the mode of IN_GENRE.")
return
}
Log.d(this::class.simpleName, "Updating song to ${song.name} and mode to $mode")
val musicStore = MusicStore.getInstance()
@ -75,12 +85,14 @@ class PlaybackViewModel : ViewModel() {
PlaybackMode.ALL_SONGS -> musicStore.songs.toMutableList()
PlaybackMode.IN_ARTIST -> song.album.artist.songs
PlaybackMode.IN_ALBUM -> song.album.songs
PlaybackMode.IN_GENRE -> error("what")
}
mCurrentParent.value = when (mode) {
PlaybackMode.ALL_SONGS -> null
PlaybackMode.IN_ARTIST -> song.album.artist
PlaybackMode.IN_ALBUM -> song.album
PlaybackMode.IN_GENRE -> error("what")
}
if (mIsShuffling.value!!) {
@ -92,6 +104,7 @@ class PlaybackViewModel : ViewModel() {
mCurrentIndex.value = mQueue.value!!.indexOf(song)
}
// Play some parent music model, whether that being albums/artists/genres.
fun play(album: Album, isShuffled: Boolean) {
Log.d(this::class.simpleName, "Playing album ${album.name}")
@ -132,6 +145,26 @@ class PlaybackViewModel : ViewModel() {
}
}
fun play(genre: Genre, isShuffled: Boolean) {
Log.d(this::class.simpleName, "Playing genre ${genre.name}")
val songs = orderSongsInGenre(genre)
updatePlayback(songs[0])
mQueue.value = songs
mCurrentIndex.value = 0
mCurrentParent.value = genre
mIsShuffling.value = isShuffled
mCurrentMode.value = PlaybackMode.IN_GENRE
if (mIsShuffling.value!!) {
genShuffle(false)
} else {
resetShuffle()
}
}
// Update the current duration using a SeekBar progress
fun updateCurrentDurationWithProgress(progress: Int) {
mCurrentDuration.value = progress.toLong()
@ -232,6 +265,7 @@ class PlaybackViewModel : ViewModel() {
mQueue.value = when (mCurrentMode.value!!) {
PlaybackMode.IN_ARTIST -> orderSongsInArtist(mCurrentParent.value as Artist)
PlaybackMode.IN_ALBUM -> orderSongsInAlbum(mCurrentParent.value as Album)
PlaybackMode.IN_GENRE -> orderSongsInGenre(mCurrentParent.value as Genre)
PlaybackMode.ALL_SONGS -> MusicStore.getInstance().songs.toMutableList()
}
@ -246,8 +280,22 @@ class PlaybackViewModel : ViewModel() {
private fun orderSongsInArtist(artist: Artist): MutableList<Song> {
val final = mutableListOf<Song>()
artist.albums.sortedByDescending { it.year }.forEach {
final.addAll(it.songs.sortedBy { it.track })
artist.albums.sortedByDescending { it.year }.forEach { album ->
final.addAll(album.songs.sortedBy { it.track })
}
return final
}
private fun orderSongsInGenre(genre: Genre): MutableList<Song> {
val final = mutableListOf<Song>()
genre.artists.sortedWith(
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
).forEach { artist ->
artist.albums.sortedByDescending { it.year }.forEach { album ->
final.addAll(album.songs.sortedBy { it.track })
}
}
return final

View file

@ -82,7 +82,7 @@ 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(
doOnClick: (Song) -> Unit,

View file

@ -3,7 +3,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />

View file

@ -4,7 +4,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M 5.88,7.06 12,13.166667 18.12,7.06 20,8.94 l -8,8 -8,-8 z" />

View file

@ -3,8 +3,7 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="m 7.5,6 h 3 v 12 h -3 z m 9,0 h -3 v 12 h 3 z" />

View file

@ -9,7 +9,6 @@ https://github.com/ashutoshgngwr/noice
<vector
android:width="32dp"
android:height="32dp"
android:alpha="1"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
@ -19,21 +18,20 @@ https://github.com/ashutoshgngwr/noice
android:pivotY="12">
<path
android:name="play_upper"
android:name="pause_right"
android:fillColor="@android:color/white"
android:pathData="M8.25,6L8.25,12L18.75,12L18.75,12Z" />
android:pathData="M 22.677734 18.898438 L 22.677734 71.810547 L 37.794922 71.810547 L 37.794922 18.898438 L 22.677734 18.898438 z" />
<path
android:name="play_lower"
android:name="pause_left"
android:fillColor="@android:color/white"
android:pathData="M8.25,18L8.25,12L18.75,12L18.75,12Z" />
android:pathData="M 52.914062 18.898438 L 52.914062 71.810547 L 68.03125 71.810547 L 68.03125 18.898438 L 52.914062 18.898438 z " />
</group>
</vector>
</aapt:attr>
<target android:name="play_upper">
<target android:name="pause_right">
<aapt:attr name="android:animation">
<set>
<objectAnimator
@ -47,7 +45,7 @@ https://github.com/ashutoshgngwr/noice
</aapt:attr>
</target>
<target android:name="play_lower">
<target android:name="pause_left">
<aapt:attr name="android:animation">
<set>
<objectAnimator

View file

@ -3,8 +3,7 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/background">
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M8.25,6L8.25,12L18.75,12L18.75,12ZM8.25,18L8.25,12L18.75,12L18.75,12Z" />

View file

@ -4,7 +4,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />

View file

@ -4,7 +4,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z" />

View file

@ -4,7 +4,7 @@
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z" />

View file

@ -4,7 +4,7 @@
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" />

View file

@ -4,7 +4,7 @@
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" />

View file

@ -4,7 +4,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/control_color">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z" />

View file

@ -5,7 +5,6 @@
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorPrimary">
<path
android:pathData="M6.542 18q-1.508-0.006-2.595-0.716-1.082-0.711-1.667-2.06-0.578-1.348-0.573-3.244 0-1.89 0.58-3.221 0.584-1.331 1.665-2.025 1.088-0.7 2.59-0.7 1.503 0 2.584 0.7 1.088 0.7 1.673 2.03 0.584 1.326 0.578 3.216 0 1.902-0.584 3.25-0.579 1.348-1.66 2.06Q8.05 18 6.542 18zm0-2.025q1.03 0 1.643-0.999 0.614-0.998 0.608-2.996 0-1.314-0.28-2.188-0.275-0.875-0.784-1.315-0.503-0.44-1.187-0.44-1.023 0-1.637 0.987-0.614 0.988-0.62 2.957 0 1.33 0.276 2.222 0.28 0.886 0.789 1.332 0.508 0.44 1.193 0.44zM17.51 6q0.924 0 1.777 0.3 0.86 0.293 1.532 0.953 0.679 0.66 1.07 1.749 0.398 1.083 0.404 2.668-0.006 1.472-0.351 2.629-0.34 1.15-0.976 1.958-0.638 0.806-1.538 1.23-0.895 0.417-2.005 0.417-1.199 0-2.117-0.446-0.918-0.45-1.479-1.224-0.555-0.779-0.672-1.749h2.496q0.146 0.632 0.614 0.982 0.468 0.344 1.158 0.344 1.169 0 1.777-0.982 0.608-0.987 0.614-2.702h-0.082Q19.463 12.635 19.007 13q-0.456 0.362-1.046 0.559-0.585 0.197-1.246 0.197-1.058 0-1.894-0.48-0.83-0.479-1.31-1.32-0.479-0.846-0.473-1.929-0.006-1.173 0.555-2.082 0.562-0.914 1.567-1.433Q16.172 5.994 17.51 6zm0.018 1.918q-0.59 0-1.053 0.271Q16.02 8.46 15.75 8.923q-0.263 0.462-0.257 1.038-0.006 0.575 0.252 1.032 0.263 0.457 0.719 0.728 0.456 0.265 1.04 0.265 0.439 0 0.807-0.158 0.374-0.158 0.65-0.434 0.28-0.282 0.438-0.65 0.158-0.372 0.163-0.795-0.005-0.558-0.269-1.02-0.263-0.463-0.725-0.734-0.461-0.277-1.04-0.277z"
android:strokeWidth="0.404319"

View file

@ -30,6 +30,8 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:menu="@menu/menu_detail"
app:popupTheme="@style/AppThemeOverlay.Popup"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Header"
app:navigationIcon="@drawable/ic_back"
app:title="@string/title_library_fragment" />
@ -103,42 +105,6 @@
app:layout_constraintTop_toBottomOf="@+id/album_artist"
tools:text="2020 / 10 Songs / 16:16" />
<ImageButton
android:id="@+id/album_play"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="@dimen/margin_tiny"
android:layout_marginEnd="@dimen/margin_tiny"
android:tint="@color/background"
android:background="@drawable/ui_circular_button"
android:backgroundTint="?android:attr/colorPrimary"
android:contentDescription="@string/description_play"
android:src="@drawable/ic_play"
android:onClick="@{() -> playbackModel.play(album, false)}"
app:layout_constraintBottom_toBottomOf="@+id/album_details"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@+id/album_shuffle"
app:layout_constraintTop_toTopOf="@+id/album_artist" />
<ImageButton
android:id="@+id/album_shuffle"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_tiny"
android:background="@drawable/ui_circular_button"
android:backgroundTint="?android:attr/colorPrimary"
android:contentDescription="@string/description_play"
android:onClick="@{() -> playbackModel.play(album, true)}"
android:src="@drawable/ic_shuffle"
android:tint="@color/background"
app:layout_constraintBottom_toBottomOf="@+id/album_details"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/album_artist" />
<TextView
android:id="@+id/album_song_header"
android:layout_width="match_parent"

View file

@ -30,6 +30,8 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:popupTheme="@style/AppThemeOverlay.Popup"
app:menu="@menu/menu_detail"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Header"
app:navigationIcon="@drawable/ic_back"
app:title="@string/title_library_fragment" />
@ -98,43 +100,6 @@
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<!-- TODO: Improve these two buttons so that they dont look as cluttered -->
<ImageButton
android:id="@+id/artist_play"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="@dimen/margin_tiny"
android:layout_marginEnd="@dimen/margin_tiny"
android:tint="@color/background"
android:background="@drawable/ui_circular_button"
android:backgroundTint="?android:attr/colorPrimary"
android:contentDescription="@string/description_play"
android:src="@drawable/ic_play"
android:onClick="@{() -> playbackModel.play(artist, false)}"
app:layout_constraintBottom_toBottomOf="@+id/artist_counts"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@+id/artist_shuffle"
app:layout_constraintTop_toTopOf="@+id/artist_genre" />
<ImageButton
android:id="@+id/artist_shuffle"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_tiny"
android:background="@drawable/ui_circular_button"
android:backgroundTint="?android:attr/colorPrimary"
android:contentDescription="@string/description_play"
android:onClick="@{() -> playbackModel.play(artist, true)}"
android:src="@drawable/ic_shuffle"
android:tint="@color/background"
app:layout_constraintBottom_toBottomOf="@+id/artist_counts"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_genre" />
<TextView
android:id="@+id/artist_album_header"
android:layout_width="match_parent"

View file

@ -30,6 +30,8 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:popupTheme="@style/AppThemeOverlay.Popup"
app:menu="@menu/menu_detail"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Header"
app:navigationIcon="@drawable/ic_back"
app:title="@string/title_library_fragment" />

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_shuffle"
android:icon="@drawable/ic_shuffle"
android:title="@string/label_shuffle"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_play"
android:title="@string/label_play"
app:showAsAction="never" />
</menu>

View file

@ -6,6 +6,7 @@
<item name="android:statusBarColor">@android:color/black</item>
<item name="android:fontFamily">@font/inter</item>
<item name="android:textCursorDrawable">@drawable/ui_cursor</item>
<item name="android:colorControlNormal">@color/control_color</item>
</style>
<!-- Toolbar Themes -->