Full song info pager on playback screen
This commit is contained in:
parent
59ee40b228
commit
69de9d6f2f
11 changed files with 366 additions and 242 deletions
|
|
@ -15,7 +15,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback
|
package org.oxycblt.auxio.playback
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
|
|
@ -33,7 +33,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.math.abs
|
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
||||||
import org.oxycblt.auxio.detail.DetailViewModel
|
import org.oxycblt.auxio.detail.DetailViewModel
|
||||||
|
|
@ -41,8 +40,8 @@ import org.oxycblt.auxio.detail.Show
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.MusicViewModel
|
import org.oxycblt.auxio.music.MusicViewModel
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.music.resolveNames
|
import org.oxycblt.auxio.playback.pager.PlaybackPageListener
|
||||||
import org.oxycblt.auxio.playback.carousel.CoverCarouselAdapter
|
import org.oxycblt.auxio.playback.pager.PlaybackPagerAdapter
|
||||||
import org.oxycblt.auxio.playback.queue.QueueViewModel
|
import org.oxycblt.auxio.playback.queue.QueueViewModel
|
||||||
import org.oxycblt.auxio.playback.state.RepeatMode
|
import org.oxycblt.auxio.playback.state.RepeatMode
|
||||||
import org.oxycblt.auxio.playback.ui.StyledSeekBar
|
import org.oxycblt.auxio.playback.ui.StyledSeekBar
|
||||||
|
|
@ -55,6 +54,7 @@ import org.oxycblt.auxio.util.share
|
||||||
import org.oxycblt.auxio.util.showToast
|
import org.oxycblt.auxio.util.showToast
|
||||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [ViewBindingFragment] more information about the currently playing song, alongside all
|
* A [ViewBindingFragment] more information about the currently playing song, alongside all
|
||||||
|
|
@ -68,13 +68,14 @@ import java.lang.reflect.Field
|
||||||
class PlaybackPanelFragment :
|
class PlaybackPanelFragment :
|
||||||
ViewBindingFragment<FragmentPlaybackPanelBinding>(),
|
ViewBindingFragment<FragmentPlaybackPanelBinding>(),
|
||||||
Toolbar.OnMenuItemClickListener,
|
Toolbar.OnMenuItemClickListener,
|
||||||
StyledSeekBar.Listener {
|
StyledSeekBar.Listener,
|
||||||
|
PlaybackPageListener {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
private val musicModel: MusicViewModel by activityViewModels()
|
private val musicModel: MusicViewModel by activityViewModels()
|
||||||
private val detailModel: DetailViewModel by activityViewModels()
|
private val detailModel: DetailViewModel by activityViewModels()
|
||||||
private val queueModel: QueueViewModel by activityViewModels()
|
private val queueModel: QueueViewModel by activityViewModels()
|
||||||
private var equalizerLauncher: ActivityResultLauncher<Intent>? = null
|
private var equalizerLauncher: ActivityResultLauncher<Intent>? = null
|
||||||
private var coverAdapter: CoverCarouselAdapter? = null
|
private var coverAdapter: PlaybackPagerAdapter? = null
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) =
|
override fun onCreateBinding(inflater: LayoutInflater) =
|
||||||
FragmentPlaybackPanelBinding.inflate(inflater)
|
FragmentPlaybackPanelBinding.inflate(inflater)
|
||||||
|
|
@ -105,7 +106,7 @@ class PlaybackPanelFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
// cover carousel adapter
|
// cover carousel adapter
|
||||||
coverAdapter = CoverCarouselAdapter()
|
coverAdapter = PlaybackPagerAdapter(this, viewLifecycleOwner)
|
||||||
binding.playbackCoverPager.apply {
|
binding.playbackCoverPager.apply {
|
||||||
adapter = coverAdapter
|
adapter = coverAdapter
|
||||||
registerOnPageChangeCallback(OnCoverChangedCallback(queueModel))
|
registerOnPageChangeCallback(OnCoverChangedCallback(queueModel))
|
||||||
|
|
@ -113,26 +114,6 @@ class PlaybackPanelFragment :
|
||||||
recycler.isNestedScrollingEnabled = false
|
recycler.isNestedScrollingEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up marquee on song information, alongside click handlers that navigate to each
|
|
||||||
// respective item.
|
|
||||||
binding.playbackSong.apply {
|
|
||||||
isSelected = true
|
|
||||||
setOnClickListener {
|
|
||||||
playbackModel.song.value?.let {
|
|
||||||
detailModel.showAlbum(it)
|
|
||||||
playbackModel.openMain()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.playbackArtist.apply {
|
|
||||||
isSelected = true
|
|
||||||
setOnClickListener { navigateToCurrentArtist() }
|
|
||||||
}
|
|
||||||
binding.playbackAlbum.apply {
|
|
||||||
isSelected = true
|
|
||||||
setOnClickListener { navigateToCurrentAlbum() }
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.playbackSeekBar.listener = this
|
binding.playbackSeekBar.listener = this
|
||||||
|
|
||||||
// Set up actions
|
// Set up actions
|
||||||
|
|
@ -159,10 +140,6 @@ class PlaybackPanelFragment :
|
||||||
equalizerLauncher = null
|
equalizerLauncher = null
|
||||||
coverAdapter = null
|
coverAdapter = null
|
||||||
binding.playbackToolbar.setOnMenuItemClickListener(null)
|
binding.playbackToolbar.setOnMenuItemClickListener(null)
|
||||||
// Marquee elements leak if they are not disabled when the views are destroyed.
|
|
||||||
binding.playbackSong.isSelected = false
|
|
||||||
binding.playbackArtist.isSelected = false
|
|
||||||
binding.playbackAlbum.isSelected = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMenuItemClick(item: MenuItem) =
|
override fun onMenuItemClick(item: MenuItem) =
|
||||||
|
|
@ -235,12 +212,7 @@ class PlaybackPanelFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val context = requireContext()
|
|
||||||
logD("Updating song display: $song")
|
logD("Updating song display: $song")
|
||||||
// binding.playbackCover.bind(song)
|
|
||||||
binding.playbackSong.text = song.name.resolve(context)
|
|
||||||
binding.playbackArtist.text = song.artists.resolveNames(context)
|
|
||||||
binding.playbackAlbum.text = song.album.name.resolve(context)
|
|
||||||
binding.playbackSeekBar.durationDs = song.durationMs.msToDs()
|
binding.playbackSeekBar.durationDs = song.durationMs.msToDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,15 +252,23 @@ class PlaybackPanelFragment :
|
||||||
is Show.AlbumArtistDecision,
|
is Show.AlbumArtistDecision,
|
||||||
is Show.GenreDetails,
|
is Show.GenreDetails,
|
||||||
is Show.PlaylistDetails,
|
is Show.PlaylistDetails,
|
||||||
null -> {}
|
null -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToCurrentArtist() {
|
override fun navigateToCurrentSong() {
|
||||||
|
playbackModel.song.value?.let {
|
||||||
|
detailModel.showAlbum(it)
|
||||||
|
playbackModel.openMain()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun navigateToCurrentArtist() {
|
||||||
playbackModel.song.value?.let(detailModel::showArtist)
|
playbackModel.song.value?.let(detailModel::showArtist)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToCurrentAlbum() {
|
override fun navigateToCurrentAlbum() {
|
||||||
playbackModel.song.value?.let { detailModel.showAlbum(it.album) }
|
playbackModel.song.value?.let { detailModel.showAlbum(it.album) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,12 +286,13 @@ class PlaybackPanelFragment :
|
||||||
super.onPageScrollStateChanged(state)
|
super.onPageScrollStateChanged(state)
|
||||||
if (state == ViewPager2.SCROLL_STATE_IDLE &&
|
if (state == ViewPager2.SCROLL_STATE_IDLE &&
|
||||||
targetPosition != RecyclerView.NO_POSITION &&
|
targetPosition != RecyclerView.NO_POSITION &&
|
||||||
targetPosition != viewModel.index.value) {
|
targetPosition != viewModel.index.value
|
||||||
|
) {
|
||||||
viewModel.goto(targetPosition)
|
viewModel.goto(targetPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val VP_RECYCLER_FIELD: Field by lazyReflectedField(ViewPager2::class, "mRecyclerView")
|
val VP_RECYCLER_FIELD: Field by lazyReflectedField(ViewPager2::class, "mRecyclerView")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 Auxio Project
|
|
||||||
* CoverCarouselAdapter.kt is part of Auxio.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback.carousel
|
|
||||||
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import org.oxycblt.auxio.databinding.ItemCoverBinding
|
|
||||||
import org.oxycblt.auxio.list.adapter.FlexibleListAdapter
|
|
||||||
import org.oxycblt.auxio.music.Song
|
|
||||||
import org.oxycblt.auxio.util.inflater
|
|
||||||
|
|
||||||
class CoverCarouselAdapter :
|
|
||||||
FlexibleListAdapter<Song, CoverViewHolder>(CoverViewHolder.DIFF_CALLBACK) {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CoverViewHolder {
|
|
||||||
return CoverViewHolder.from(parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: CoverViewHolder, position: Int) {
|
|
||||||
holder.bind(getItem(position))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CoverViewHolder private constructor(private val binding: ItemCoverBinding) :
|
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
|
||||||
/**
|
|
||||||
* Bind new data to this instance.
|
|
||||||
*
|
|
||||||
* @param item The new [Song] to bind.
|
|
||||||
*/
|
|
||||||
fun bind(item: Song) {
|
|
||||||
binding.playbackCover.bind(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new instance.
|
|
||||||
*
|
|
||||||
* @param parent The parent to inflate this instance from.
|
|
||||||
* @return A new instance.
|
|
||||||
*/
|
|
||||||
fun from(parent: ViewGroup) =
|
|
||||||
CoverViewHolder(ItemCoverBinding.inflate(parent.context.inflater, parent, false))
|
|
||||||
|
|
||||||
/** A comparator that can be used with DiffUtil. */
|
|
||||||
val DIFF_CALLBACK =
|
|
||||||
object : DiffUtil.ItemCallback<Song>() {
|
|
||||||
override fun areItemsTheSame(oldItem: Song, newItem: Song) =
|
|
||||||
oldItem.uid == newItem.uid
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: Song, newItem: Song) =
|
|
||||||
oldItem.album.coverUri == newItem.album.coverUri
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
* PlaybackPageListener.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.playback.pager
|
||||||
|
|
||||||
|
interface PlaybackPageListener {
|
||||||
|
|
||||||
|
fun navigateToCurrentArtist()
|
||||||
|
|
||||||
|
fun navigateToCurrentAlbum()
|
||||||
|
|
||||||
|
fun navigateToCurrentSong()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
* PlaybackPagerAdapter.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.playback.pager
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.databinding.ItemPlaybackSongBinding
|
||||||
|
import org.oxycblt.auxio.list.adapter.FlexibleListAdapter
|
||||||
|
import org.oxycblt.auxio.music.Song
|
||||||
|
import org.oxycblt.auxio.music.resolveNames
|
||||||
|
import org.oxycblt.auxio.util.inflater
|
||||||
|
import kotlin.jvm.internal.Intrinsics
|
||||||
|
|
||||||
|
class PlaybackPagerAdapter(
|
||||||
|
private val listener: PlaybackPageListener,
|
||||||
|
private val lifecycleOwner: LifecycleOwner
|
||||||
|
) : FlexibleListAdapter<Song, CoverViewHolder>(CoverViewHolder.DIFF_CALLBACK) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CoverViewHolder {
|
||||||
|
return CoverViewHolder.from(parent, listener).also {
|
||||||
|
lifecycleOwner.lifecycle.addObserver(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CoverViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewRecycled(holder: CoverViewHolder) {
|
||||||
|
holder.recycle()
|
||||||
|
super.onViewRecycled(holder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoverViewHolder
|
||||||
|
private constructor(
|
||||||
|
private val binding: ItemPlaybackSongBinding,
|
||||||
|
private val listener: PlaybackPageListener
|
||||||
|
) : RecyclerView.ViewHolder(binding.root), DefaultLifecycleObserver, View.OnClickListener {
|
||||||
|
|
||||||
|
init {
|
||||||
|
binding.playbackSong.setOnClickListener(this)
|
||||||
|
binding.playbackArtist.setOnClickListener(this)
|
||||||
|
binding.playbackAlbum.setOnClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v.id) {
|
||||||
|
R.id.playback_album -> listener.navigateToCurrentAlbum()
|
||||||
|
R.id.playback_artist -> listener.navigateToCurrentArtist()
|
||||||
|
R.id.playback_song -> listener.navigateToCurrentSong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
|
super.onResume(owner)
|
||||||
|
setSelected(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
|
super.onPause(owner)
|
||||||
|
setSelected(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy(owner: LifecycleOwner) {
|
||||||
|
super.onDestroy(owner)
|
||||||
|
owner.lifecycle.removeObserver(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind new data to this instance.
|
||||||
|
*
|
||||||
|
* @param item The new [Song] to bind.
|
||||||
|
*/
|
||||||
|
fun bind(item: Song) {
|
||||||
|
binding.playbackCover.bind(item)
|
||||||
|
val context = binding.root.context
|
||||||
|
binding.playbackSong.text = item.name.resolve(context)
|
||||||
|
binding.playbackArtist.text = item.artists.resolveNames(context)
|
||||||
|
binding.playbackAlbum.text = item.album.name.resolve(context)
|
||||||
|
setSelected(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun recycle() {
|
||||||
|
// Marquee elements leak if they are not disabled when the views are destroyed.
|
||||||
|
setSelected(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setSelected(value: Boolean) {
|
||||||
|
binding.playbackSong.isSelected = value
|
||||||
|
binding.playbackArtist.isSelected = value
|
||||||
|
binding.playbackAlbum.isSelected = value
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param parent The parent to inflate this instance from.
|
||||||
|
* @return A new instance.
|
||||||
|
*/
|
||||||
|
fun from(parent: ViewGroup, listener: PlaybackPageListener) =
|
||||||
|
CoverViewHolder(
|
||||||
|
ItemPlaybackSongBinding.inflate(parent.context.inflater, parent, false),
|
||||||
|
listener
|
||||||
|
)
|
||||||
|
|
||||||
|
/** A comparator that can be used with DiffUtil. */
|
||||||
|
val DIFF_CALLBACK =
|
||||||
|
object : DiffUtil.ItemCallback<Song>() {
|
||||||
|
override fun areItemsTheSame(oldItem: Song, newItem: Song) =
|
||||||
|
oldItem.uid == newItem.uid
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: Song, newItem: Song): Boolean {
|
||||||
|
return Intrinsics.areEqual(oldItem, newItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,49 +18,12 @@
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/playback_cover_pager"
|
android:id="@+id/playback_cover_pager"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
android:layout_width="0dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_song"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_song"
|
|
||||||
style="@style/Widget.Auxio.TextView.Primary"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_artist"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="Song Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_artist"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
tools:text="Artist Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_album"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:text="Album Name" />
|
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" />
|
||||||
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
||||||
android:id="@+id/playback_seek_bar"
|
android:id="@+id/playback_seek_bar"
|
||||||
|
|
|
||||||
56
app/src/main/res/layout-h480dp/item_playback_song.xml
Normal file
56
app/src/main/res/layout-h480dp/item_playback_song.xml
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<org.oxycblt.auxio.image.CoverView
|
||||||
|
android:id="@+id/playback_cover"
|
||||||
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
app:enablePlaybackIndicator="false"
|
||||||
|
app:enableSelectionBadge="false"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/playback_song"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_song"
|
||||||
|
style="@style/Widget.Auxio.TextView.Primary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/playback_artist"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:text="Song Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_artist"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="Artist Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_album"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="Album Name" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -18,49 +18,12 @@
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/playback_cover_pager"
|
android:id="@+id/playback_cover_pager"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_song"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_song"
|
|
||||||
style="@style/Widget.Auxio.TextView.Primary"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_artist"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="Song Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_artist"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
tools:text="Artist Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_album"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:text="Album Name" />
|
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" />
|
||||||
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
||||||
android:id="@+id/playback_seek_bar"
|
android:id="@+id/playback_seek_bar"
|
||||||
|
|
|
||||||
56
app/src/main/res/layout-sw600dp/item_playback_song.xml
Normal file
56
app/src/main/res/layout-sw600dp/item_playback_song.xml
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<org.oxycblt.auxio.image.CoverView
|
||||||
|
android:id="@+id/playback_cover"
|
||||||
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
app:enablePlaybackIndicator="false"
|
||||||
|
app:enableSelectionBadge="false"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/playback_song"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_song"
|
||||||
|
style="@style/Widget.Auxio.TextView.Primary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/playback_artist"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:text="Song Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_artist"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="Artist Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_album"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="Album Name" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -18,56 +18,20 @@
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/playback_cover_pager"
|
android:id="@+id/playback_cover_pager"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
|
||||||
app:layout_constraintVertical_chainStyle="packed" />
|
app:layout_constraintVertical_chainStyle="packed" />
|
||||||
|
|
||||||
<!-- Playback information is wrapped in a container so that marquee doesn't break -->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/playback_info_container"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_cover_pager"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_cover_pager"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_song"
|
|
||||||
style="@style/Widget.Auxio.TextView.Primary"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="Song Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_artist"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="Artist Name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/playback_album"
|
|
||||||
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="Album Name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
<org.oxycblt.auxio.playback.ui.StyledSeekBar
|
||||||
android:id="@+id/playback_seek_bar"
|
android:id="@+id/playback_seek_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
|
app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/playback_info_container"
|
app:layout_constraintEnd_toEndOf="@+id/playback_cover_pager"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<org.oxycblt.auxio.image.CoverView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/playback_cover"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:enablePlaybackIndicator="false"
|
|
||||||
app:enableSelectionBadge="false"
|
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
|
||||||
app:sizing="large" />
|
|
||||||
55
app/src/main/res/layout/item_playback_song.xml
Normal file
55
app/src/main/res/layout/item_playback_song.xml
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<org.oxycblt.auxio.image.CoverView
|
||||||
|
android:id="@+id/playback_cover"
|
||||||
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
app:enablePlaybackIndicator="false"
|
||||||
|
app:enableSelectionBadge="false"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<!-- Playback information is wrapped in a container so that marquee doesn't break -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/playback_info_container"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/spacing_medium"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_song"
|
||||||
|
style="@style/Widget.Auxio.TextView.Primary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="Song Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_artist"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="Artist Name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playback_album"
|
||||||
|
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="Album Name" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Loading…
Reference in a new issue