Add play buttons to other Detail Fragments
Add play buttons to the ArtistDetailFragment & GenreDetailFragment.
This commit is contained in:
parent
a64627c7cf
commit
c17666752b
11 changed files with 157 additions and 36 deletions
|
@ -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
|
||||
|
|
|
@ -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 ->
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -67,7 +70,7 @@ class PlaybackViewModel : ViewModel() {
|
|||
Log.d(
|
||||
this::class.simpleName,
|
||||
"update() was called with IN_GENRES, using " +
|
||||
"most prominent genre instead of the song's genre."
|
||||
"most prominent genre instead of the song's genre."
|
||||
)
|
||||
|
||||
song.album.artist.genres[0].songs
|
||||
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
<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" />
|
||||
</vector>
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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" />
|
||||
|
||||
|
|
Loading…
Reference in a new issue