Add play buttons to other Detail Fragments

Add play buttons to the ArtistDetailFragment & GenreDetailFragment.
This commit is contained in:
OxygenCobalt 2020-10-14 15:49:49 -06:00
parent a64627c7cf
commit c17666752b
11 changed files with 157 additions and 36 deletions

View file

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout
@ -14,6 +15,7 @@ import com.google.android.material.tabs.TabLayoutMediator
import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.library.LibraryFragment
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.songs.SongsFragment
import org.oxycblt.auxio.theme.accent
import org.oxycblt.auxio.theme.getInactiveAlpha
@ -21,6 +23,8 @@ import org.oxycblt.auxio.theme.getTransparentAccent
import org.oxycblt.auxio.theme.toColor
class MainFragment : Fragment() {
private val playbackModel: PlaybackViewModel by activityViewModels()
private val shownFragments = listOf(0, 1)
private val tabIcons = listOf(
R.drawable.ic_library,
@ -83,6 +87,23 @@ class MainFragment : Fragment() {
}
)
// --- VIEWMODEL SETUP ---
// TODO: Add a slide animation to this
// Change CompactPlaybackFragment's visibility here so that an animation occurs.
playbackModel.currentSong.observe(viewLifecycleOwner) {
if (it == null) {
Log.d(
this::class.simpleName,
"Hiding CompactPlaybackFragment since no song is being played."
)
binding.compactPlayback.visibility = View.GONE
} else {
binding.compactPlayback.visibility = View.VISIBLE
}
}
Log.d(this::class.simpleName, "Fragment Created.")
return binding.root

View file

@ -5,7 +5,6 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
@ -49,9 +48,6 @@ class AlbumDetailFragment : Fragment() {
playbackModel.update(it, PlaybackMode.IN_ALBUM)
}
val playIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_play)
val pauseIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_pause)
// --- UI SETUP ---
binding.lifecycleOwner = this
@ -125,9 +121,9 @@ class AlbumDetailFragment : Fragment() {
}
// Update the play button depending on the current playback status
// If the shown album is currently playing, set the button to the current isPlaying status and
// its behavior to modify the current playing status
// If the shown album isn't currently playing, set the button to "Play" and its behavior
// If the shown album is currently playing, set the button icon to the current isPlaying
// status, and then set its behavior to modify isPlaying.
// If the shown album isn't currently playing, set the button to Play and its behavior
// to start the playback of the album.
private fun updatePlayButton(mode: PlaybackMode, binding: FragmentAlbumDetailBinding) {
playbackModel.currentSong.value?.let { song ->

View file

@ -9,9 +9,12 @@ 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.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
@ -22,6 +25,7 @@ class ArtistDetailFragment : Fragment() {
private val args: ArtistDetailFragmentArgs by navArgs()
private val detailModel: DetailViewModel by activityViewModels()
private val playbackModel: PlaybackViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
@ -56,6 +60,7 @@ class ArtistDetailFragment : Fragment() {
binding.lifecycleOwner = this
binding.detailModel = detailModel
binding.playbackModel = playbackModel
binding.artist = detailModel.currentArtist.value!!
binding.artistToolbar.setNavigationOnClickListener {
@ -87,11 +92,48 @@ 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 the shown artist is currently playing, set the button icon to the current isPlaying
// status, and then set its behavior to modify isPlaying.
// If the shown artist isn't currently playing, set the button to Play and its behavior
// to start the playback of the artist.
private fun updatePlayButton(mode: PlaybackMode, binding: FragmentArtistDetailBinding) {
playbackModel.currentSong.value?.let { song ->
if (mode == PlaybackMode.IN_ARTIST &&
song.album.artist == detailModel.currentArtist.value
) {
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.currentArtist.value!!, false)
}
}
}
}
override fun onResume() {
super.onResume()

View file

@ -9,9 +9,12 @@ 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.PlaybackMode
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.theme.applyDivider
import org.oxycblt.auxio.theme.disable
@ -19,6 +22,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,
@ -53,6 +57,7 @@ class GenreDetailFragment : Fragment() {
binding.lifecycleOwner = this
binding.detailModel = detailModel
binding.playbackModel = playbackModel
binding.genre = detailModel.currentGenre.value
binding.genreToolbar.setNavigationOnClickListener {
@ -84,6 +89,14 @@ class GenreDetailFragment : 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
@ -94,4 +107,27 @@ class GenreDetailFragment : Fragment() {
detailModel.updateNavigationStatus(false)
}
private fun updatePlayButton(mode: PlaybackMode, binding: FragmentGenreDetailBinding) {
if (mode == PlaybackMode.IN_GENRE &&
detailModel.currentGenre.value == playbackModel.currentGenre.value
) {
Log.d(this::class.simpleName, "Retard")
if (playbackModel.isPlaying.value!!) {
binding.genrePlay.setImageResource(R.drawable.ic_pause)
} else {
binding.genrePlay.setImageResource(R.drawable.ic_play)
}
binding.genrePlay.setOnClickListener {
playbackModel.invertPlayingStatus()
}
} else {
binding.genrePlay.setImageResource(R.drawable.ic_play)
binding.genrePlay.setOnClickListener {
playbackModel.play(detailModel.currentGenre.value!!, false)
}
}
}
}

View file

@ -25,6 +25,7 @@ class CompactPlaybackFragment : Fragment() {
): View? {
val binding = FragmentCompactPlaybackBinding.inflate(inflater)
// FIXME: Stop these icons from self-animating on creation.
val iconPauseToPlay = ContextCompat.getDrawable(
requireContext(), R.drawable.ic_pause_to_play
) as AnimatedVectorDrawable
@ -41,7 +42,6 @@ class CompactPlaybackFragment : Fragment() {
// as for some reason the attach event doesn't register anymore w/LiveData
binding.song = MusicStore.getInstance().songs[0]
binding.playbackModel = playbackModel
binding.root.visibility = View.GONE
binding.root.setOnClickListener {
findNavController().navigate(
@ -51,18 +51,12 @@ class CompactPlaybackFragment : Fragment() {
// --- VIEWMODEL SETUP ---
// TODO: Add some kind of animation to when this view becomes visible/invisible.
playbackModel.currentSong.observe(viewLifecycleOwner) {
if (it == null) {
Log.d(this::class.simpleName, "Hiding playback bar due to no song being played.")
binding.root.visibility = View.GONE
} else {
if (it != null) {
Log.d(this::class.simpleName, "Updating song display to ${it.name}")
binding.song = it
binding.playbackProgress.max = it.seconds.toInt()
binding.root.visibility = View.VISIBLE
}
}

View file

@ -37,9 +37,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
val accentColor = ColorStateList.valueOf(accent.first.toColor(requireContext()))
val controlColor = ColorStateList.valueOf(R.color.control_color.toColor(requireContext()))
val normalTextColor = binding.playbackDurationCurrent.currentTextColor
val disabledColor = ColorStateList.valueOf(
R.color.inactive_color.toColor(requireContext())
)
val iconPauseToPlay = ContextCompat.getDrawable(
requireContext(), R.drawable.ic_pause_to_play

View file

@ -21,6 +21,9 @@ class PlaybackViewModel : ViewModel() {
private val mCurrentSong = MutableLiveData<Song>()
val currentSong: LiveData<Song> get() = mCurrentSong
private val mCurrentGenre = MutableLiveData<Genre>()
val currentGenre: LiveData<Genre> get() = mCurrentGenre
private val mQueue = MutableLiveData(mutableListOf<Song>())
val queue: LiveData<MutableList<Song>> get() = mQueue
@ -109,6 +112,7 @@ class PlaybackViewModel : ViewModel() {
updatePlayback(songs[0])
mCurrentGenre.value = genre
mQueue.value = songs
mCurrentIndex.value = 0
mCurrentMode.value = PlaybackMode.IN_GENRE
@ -141,7 +145,7 @@ class PlaybackViewModel : ViewModel() {
private fun orderSongsInGenre(genre: Genre): MutableList<Song> {
val final = mutableListOf<Song>()
genre.artists.sortedBy { it.name }.forEach { artist ->
genre.artists.sortedByDescending { it.name }.forEach { artist ->
artist.albums.sortedByDescending { it.year }.forEach { album ->
final.addAll(album.songs.sortedBy { it.track })
}

View file

@ -5,20 +5,7 @@
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/background">
<group
android:pivotX="12"
android:pivotY="12"
android:rotation="-90">
<path
android:name="pause_upper"
android:fillColor="@android:color/white"
android:pathData="M6,7.5L6,10.5L18,10.5L18,7.5Z" />
<path
android:name="pause_lower"
android:fillColor="@android:color/white"
android:pathData="M6,16.5L6,13.5L18,13.5L18,16.5Z" />
</group>
android:pathData="m 7.5,6 h 3 v 12 h -3 z m 9,0 h -3 v 12 h 3 z" />
</vector>

View file

@ -13,6 +13,10 @@
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<LinearLayout
@ -94,6 +98,23 @@
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<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_medium"
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_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_genre" />
<TextView
android:id="@+id/artist_album_header"
android:layout_width="match_parent"

View file

@ -13,6 +13,10 @@
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<LinearLayout
@ -95,6 +99,23 @@
app:layout_constraintTop_toBottomOf="@+id/genre_counts"
tools:text="80 Songs" />
<ImageButton
android:id="@+id/genre_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_medium"
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(genre, false)}"
app:layout_constraintBottom_toBottomOf="@+id/genre_song_count"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/genre_counts" />
<TextView
android:id="@+id/genre_artist_header"
android:layout_width="match_parent"

View file

@ -5,6 +5,7 @@
tools:context=".MainFragment">
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
@ -20,6 +21,7 @@
android:id="@+id/compact_playback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:name="org.oxycblt.auxio.playback.CompactPlaybackFragment"
android:elevation="@dimen/elevation_normal" />