playback: rework view implementations
Rework the playback views to follow the new idioms I want to use for Auxio. This change mostly consists of flattening away some of the custom views, removing databinding, and using a general viewbinding fragment that I hope to extend to the entire app.
This commit is contained in:
parent
e4d4266e35
commit
8f38ed6ee5
18 changed files with 394 additions and 360 deletions
|
@ -21,6 +21,7 @@ import android.content.Context
|
|||
import android.graphics.Bitmap
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.databinding.BindingAdapter
|
||||
import coil.dispose
|
||||
|
@ -37,23 +38,28 @@ import org.oxycblt.auxio.music.Song
|
|||
|
||||
// --- BINDING ADAPTERS ---
|
||||
|
||||
/** Bind the album art for a [song]. */
|
||||
/** Bind the album cover for a [song]. */
|
||||
@BindingAdapter("albumArt")
|
||||
fun ImageView.bindAlbumArt(song: Song?) = load(song, R.drawable.ic_album)
|
||||
fun ImageView.bindAlbumCover(song: Song?) =
|
||||
load(song, R.drawable.ic_album, R.string.desc_album_cover)
|
||||
|
||||
/** Bind the album art for an [album]. */
|
||||
/** Bind the album cover for an [album]. */
|
||||
@BindingAdapter("albumArt")
|
||||
fun ImageView.bindAlbumArt(album: Album?) = load(album, R.drawable.ic_album)
|
||||
fun ImageView.bindAlbumCover(album: Album?) =
|
||||
load(album, R.drawable.ic_album, R.string.desc_album_cover)
|
||||
|
||||
/** Bind the image for an [artist] */
|
||||
@BindingAdapter("artistImage")
|
||||
fun ImageView.bindArtistImage(artist: Artist?) = load(artist, R.drawable.ic_artist)
|
||||
fun ImageView.bindArtistImage(artist: Artist?) =
|
||||
load(artist, R.drawable.ic_artist, R.string.desc_artist_image)
|
||||
|
||||
/** Bind the image for a [genre] */
|
||||
@BindingAdapter("genreImage")
|
||||
fun ImageView.bindGenreImage(genre: Genre?) = load(genre, R.drawable.ic_genre)
|
||||
fun ImageView.bindGenreImage(genre: Genre?) =
|
||||
load(genre, R.drawable.ic_genre, R.string.desc_genre_image)
|
||||
|
||||
fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int) {
|
||||
fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int, @StringRes desc: Int) {
|
||||
contentDescription = context.getString(desc, music?.resolvedName)
|
||||
dispose()
|
||||
load(music) {
|
||||
error(error)
|
||||
|
|
|
@ -24,7 +24,7 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumArt
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
|
@ -127,7 +127,7 @@ class AlbumDetailAdapter(
|
|||
|
||||
override fun onBind(data: Album) {
|
||||
binding.detailCover.apply {
|
||||
bindAlbumArt(data)
|
||||
bindAlbumCover(data)
|
||||
contentDescription = context.getString(R.string.desc_album_cover, data.resolvedName)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,10 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.music.bindSongInfo
|
||||
import org.oxycblt.auxio.ui.BottomSheetLayout
|
||||
import org.oxycblt.auxio.util.getAttrColorSafe
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
@ -99,27 +101,25 @@ class PlaybackBarFragment : Fragment() {
|
|||
|
||||
// -- VIEWMODEL SETUP ---
|
||||
|
||||
binding.song = playbackModel.song.value
|
||||
playbackModel.song.observe(viewLifecycleOwner) { song ->
|
||||
if (song != null) {
|
||||
binding.song = song
|
||||
binding.executePendingBindings()
|
||||
binding.playbackCover.bindAlbumCover(song)
|
||||
binding.playbackSong.text = song.resolvedName
|
||||
binding.playbackInfo.bindSongInfo(song)
|
||||
binding.playbackProgressBar.max = song.seconds.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
binding.playbackPlayPause.isActivated = playbackModel.isPlaying.value!!
|
||||
playbackModel.isPlaying.observe(viewLifecycleOwner) { isPlaying ->
|
||||
binding.playbackPlayPause.isActivated = isPlaying
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
binding.playbackProgressBar.progress = playbackModel.position.value!!.toInt()
|
||||
playbackModel.position.observe(viewLifecycleOwner) { position ->
|
||||
binding.playbackProgressBar.progress = playbackModel.seconds.value!!.toInt()
|
||||
playbackModel.seconds.observe(viewLifecycleOwner) { position ->
|
||||
binding.playbackProgressBar.progress = position.toInt()
|
||||
}
|
||||
|
||||
binding.executePendingBindings()
|
||||
|
||||
return binding.root
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,25 @@ package org.oxycblt.auxio.playback
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.slider.Slider
|
||||
import kotlin.math.max
|
||||
import org.oxycblt.auxio.MainFragmentDirections
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.music.toDuration
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.ui.BottomSheetLayout
|
||||
import org.oxycblt.auxio.ui.ViewBindingFragment
|
||||
import org.oxycblt.auxio.util.getAttrColorSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.stateList
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
||||
/**
|
||||
|
@ -42,28 +48,25 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
|||
*
|
||||
* TODO: Handle RTL correctly in the playback buttons
|
||||
*/
|
||||
class PlaybackPanelFragment : Fragment() {
|
||||
class PlaybackPanelFragment :
|
||||
ViewBindingFragment<FragmentPlaybackPanelBinding>(),
|
||||
Slider.OnChangeListener,
|
||||
Slider.OnSliderTouchListener {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private var lastBinding: FragmentPlaybackPanelBinding? = null
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
override fun onCreateBinding(inflater: LayoutInflater): FragmentPlaybackPanelBinding {
|
||||
return FragmentPlaybackPanelBinding.inflate(inflater)
|
||||
}
|
||||
|
||||
override fun onBindingCreated(
|
||||
binding: FragmentPlaybackPanelBinding,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val binding = FragmentPlaybackPanelBinding.inflate(layoutInflater)
|
||||
) {
|
||||
val queueItem: MenuItem
|
||||
|
||||
// See onDestroyView for why we do this
|
||||
lastBinding = binding
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.playbackModel = playbackModel
|
||||
binding.detailModel = detailModel
|
||||
|
||||
binding.root.setOnApplyWindowInsetsListener { _, insets ->
|
||||
val bars = insets.systemBarInsetsCompat
|
||||
binding.root.updatePadding(top = bars.top, bottom = bars.bottom)
|
||||
|
@ -85,20 +88,62 @@ class PlaybackPanelFragment : Fragment() {
|
|||
queueItem = menu.findItem(R.id.action_queue)
|
||||
}
|
||||
|
||||
// Make marquee of song title work
|
||||
binding.playbackSong.isSelected = true
|
||||
binding.playbackSeekBar.onConfirmListener = playbackModel::setPosition
|
||||
binding.playbackSong.apply {
|
||||
// Make marquee of the song title work
|
||||
isSelected = true
|
||||
setOnClickListener { playbackModel.song.value?.let { detailModel.navToItem(it) } }
|
||||
}
|
||||
|
||||
// Abuse the play/pause FAB (see style definition for more info)
|
||||
binding.playbackPlayPause.post { binding.playbackPlayPause.stateListAnimator = null }
|
||||
binding.playbackArtist.setOnClickListener {
|
||||
playbackModel.song.value?.let { detailModel.navToItem(it.album.artist) }
|
||||
}
|
||||
|
||||
binding.playbackAlbum.setOnClickListener {
|
||||
playbackModel.song.value?.let { detailModel.navToItem(it.album) }
|
||||
}
|
||||
|
||||
binding.playbackSeekBar.apply {
|
||||
addOnChangeListener(this@PlaybackPanelFragment)
|
||||
addOnSliderTouchListener(this@PlaybackPanelFragment)
|
||||
|
||||
// Composite a tint list based on the active/inactive colors
|
||||
trackInactiveTintList =
|
||||
MaterialColors.compositeARGBWithAlpha(
|
||||
context.getAttrColorSafe(R.attr.colorSecondary), (255 * 0.2).toInt())
|
||||
.stateList
|
||||
}
|
||||
|
||||
binding.playbackLoop.setOnClickListener { playbackModel.incrementLoopStatus() }
|
||||
|
||||
binding.playbackSkipPrev.setOnClickListener { playbackModel.skipPrev() }
|
||||
|
||||
binding.playbackPlayPause.apply {
|
||||
// Abuse the play/pause FAB (see style definition for more info)
|
||||
post { binding.playbackPlayPause.stateListAnimator = null }
|
||||
setOnClickListener { playbackModel.invertPlayingStatus() }
|
||||
}
|
||||
|
||||
binding.playbackSkipNext.setOnClickListener { playbackModel.skipNext() }
|
||||
|
||||
binding.playbackShuffle.setOnClickListener { playbackModel.invertShuffleStatus() }
|
||||
|
||||
// --- VIEWMODEL SETUP --
|
||||
|
||||
playbackModel.song.observe(viewLifecycleOwner) { song ->
|
||||
if (song != null) {
|
||||
logD("Updating song display to ${song.rawName}")
|
||||
binding.song = song
|
||||
binding.playbackSeekBar.setDuration(song.seconds)
|
||||
binding.playbackCover.bindAlbumCover(song)
|
||||
binding.playbackSong.text = song.resolvedName
|
||||
binding.playbackArtist.text = song.resolvedArtistName
|
||||
binding.playbackAlbum.text = song.resolvedAlbumName
|
||||
|
||||
// Normally if a song had a duration
|
||||
val seconds = song.seconds
|
||||
binding.playbackDuration.text = seconds.toDuration(false)
|
||||
binding.playbackSeekBar.apply {
|
||||
valueTo = max(seconds, 1L).toFloat()
|
||||
isEnabled = seconds > 0L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,8 +170,13 @@ class PlaybackPanelFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
playbackModel.position.observe(viewLifecycleOwner) { pos ->
|
||||
binding.playbackSeekBar.setProgress(pos)
|
||||
playbackModel.seconds.observe(viewLifecycleOwner) { pos ->
|
||||
// Don't update the progress while we are seeking, that will make the SeekBar jump
|
||||
// around.
|
||||
if (!binding.playbackSeconds.isActivated) {
|
||||
binding.playbackSeekBar.value = pos.toFloat()
|
||||
binding.playbackSeconds.text = pos.toDuration(true)
|
||||
}
|
||||
}
|
||||
|
||||
playbackModel.nextUp.observe(viewLifecycleOwner) {
|
||||
|
@ -146,17 +196,27 @@ class PlaybackPanelFragment : Fragment() {
|
|||
}
|
||||
|
||||
logD("Fragment Created")
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) {
|
||||
binding.playbackSong.isSelected = false
|
||||
binding.playbackSeekBar.removeOnChangeListener(this)
|
||||
binding.playbackSeekBar.removeOnChangeListener(this)
|
||||
}
|
||||
|
||||
// playbackSong will leak if we don't disable marquee, keep the binding around
|
||||
// so that we can turn it off when we destroy the view.
|
||||
lastBinding?.playbackSong?.isSelected = false
|
||||
lastBinding = null
|
||||
override fun onStartTrackingTouch(slider: Slider) {
|
||||
requireBinding().playbackSeconds.isActivated = true
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(slider: Slider) {
|
||||
requireBinding().playbackSeconds.isActivated = false
|
||||
playbackModel.setPosition(slider.value.toLong())
|
||||
}
|
||||
|
||||
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
requireBinding().playbackSeconds.text = value.toLong().toDuration(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateUp() {
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
*
|
||||
* 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
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.slider.Slider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ViewSeekBarBinding
|
||||
import org.oxycblt.auxio.music.toDuration
|
||||
import org.oxycblt.auxio.util.getAttrColorSafe
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.stateList
|
||||
|
||||
/**
|
||||
* A custom view that bundles together a seekbar with a current duration and a total duration. The
|
||||
* sub-views are specifically laid out so that the seekbar has an adequate touch height while still
|
||||
* not having gobs of whitespace everywhere.
|
||||
*
|
||||
* TODO: Add smooth seeking [i.e seeking in sub-second values]
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
@SuppressLint("RestrictedApi")
|
||||
class PlaybackSeekBar
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, defStyleRes: Int = 0) :
|
||||
ConstraintLayout(context, attrs, defStyleRes),
|
||||
Slider.OnChangeListener,
|
||||
Slider.OnSliderTouchListener {
|
||||
private val binding = ViewSeekBarBinding.inflate(context.inflater, this, true)
|
||||
private val isSeeking: Boolean
|
||||
get() = binding.playbackDurationCurrent.isActivated
|
||||
|
||||
var onConfirmListener: ((Long) -> Unit)? = null
|
||||
|
||||
init {
|
||||
binding.seekBar.addOnChangeListener(this)
|
||||
binding.seekBar.addOnSliderTouchListener(this)
|
||||
|
||||
// Override the inactive color so that it lines up with the playback progress bar.
|
||||
binding.seekBar.trackInactiveTintList =
|
||||
MaterialColors.compositeARGBWithAlpha(
|
||||
context.getAttrColorSafe(R.attr.colorSecondary), (255 * 0.2).toInt())
|
||||
.stateList
|
||||
}
|
||||
|
||||
fun setProgress(seconds: Long) {
|
||||
// Don't update the progress while we are seeking, that will make the SeekBar jump around.
|
||||
if (!isSeeking) {
|
||||
binding.seekBar.value = seconds.toFloat()
|
||||
binding.playbackDurationCurrent.text = seconds.toDuration(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun setDuration(seconds: Long) {
|
||||
if (seconds == 0L) {
|
||||
// One of two things occurred:
|
||||
// - Android couldn't get the total duration of the song
|
||||
// - The duration of the song was so low as to be rounded to zero when converted
|
||||
// to seconds.
|
||||
// In either of these cases, the seekbar is more or less useless. Disable it.
|
||||
logD("Duration is 0, entering disabled state")
|
||||
binding.seekBar.apply {
|
||||
valueTo = 1f
|
||||
isEnabled = false
|
||||
}
|
||||
} else {
|
||||
binding.seekBar.apply {
|
||||
valueTo = seconds.toFloat()
|
||||
isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
binding.playbackSongDuration.text = seconds.toDuration(false)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(slider: Slider) {
|
||||
binding.playbackDurationCurrent.isActivated = true
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(slider: Slider) {
|
||||
binding.playbackDurationCurrent.isActivated = false
|
||||
onConfirmListener?.invoke(slider.value.toLong())
|
||||
}
|
||||
|
||||
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
// Don't actually seek yet when the user moves the progress bar, as to make our
|
||||
// player seek during every movement is both inefficient and weird.
|
||||
binding.playbackDurationCurrent.text = value.toLong().toDuration(true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -58,7 +58,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
private val mIsPlaying = MutableLiveData(false)
|
||||
private val mIsShuffling = MutableLiveData(false)
|
||||
private val mLoopMode = MutableLiveData(LoopMode.NONE)
|
||||
private val mPosition = MutableLiveData(0L)
|
||||
private val mSeconds = MutableLiveData(0L)
|
||||
|
||||
// Queue
|
||||
private val mNextUp = MutableLiveData(listOf<Song>())
|
||||
|
@ -82,8 +82,8 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
val loopMode: LiveData<LoopMode>
|
||||
get() = mLoopMode
|
||||
/** The current playback position, in seconds */
|
||||
val position: LiveData<Long>
|
||||
get() = mPosition
|
||||
val seconds: LiveData<Long>
|
||||
get() = mSeconds
|
||||
|
||||
/** The queue, without the previous items. */
|
||||
val nextUp: LiveData<List<Song>>
|
||||
|
@ -336,7 +336,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
}
|
||||
|
||||
override fun onPositionUpdate(position: Long) {
|
||||
mPosition.value = position / 1000
|
||||
mSeconds.value = position / 1000
|
||||
}
|
||||
|
||||
override fun onQueueUpdate(queue: List<Song>, index: Int) {
|
||||
|
|
|
@ -162,6 +162,8 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
|
|||
// / --- CONTROL METHODS ---
|
||||
|
||||
/**
|
||||
* Show the panel, only if it's hidden.
|
||||
* @return if the panel was shown
|
||||
*/
|
||||
fun show(): Boolean {
|
||||
if (panelState == PanelState.HIDDEN) {
|
||||
|
@ -172,6 +174,10 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
|
|||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the panel if it is currently collapsed.
|
||||
* @return If the panel was expanded
|
||||
*/
|
||||
fun expand(): Boolean {
|
||||
if (panelState == PanelState.COLLAPSED) {
|
||||
applyState(PanelState.EXPANDED)
|
||||
|
@ -183,7 +189,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
|
|||
|
||||
/**
|
||||
* Collapse the panel if it is currently expanded.
|
||||
* @return If the panel was collapsed or not.
|
||||
* @return If the panel was collapsed
|
||||
*/
|
||||
fun collapse(): Boolean {
|
||||
if (panelState == PanelState.EXPANDED) {
|
||||
|
@ -195,6 +201,8 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
|
|||
}
|
||||
|
||||
/**
|
||||
* Hide the panel if it is not hidden.
|
||||
* @return If the panel was hidden
|
||||
*/
|
||||
fun hide(): Boolean {
|
||||
if (panelState != PanelState.HIDDEN) {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Auxio Project
|
||||
*
|
||||
* 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.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
/** A fragment enabling ViewBinding inflation and usage across the fragment lifecycle. */
|
||||
abstract class ViewBindingFragment<T : ViewBinding> : Fragment() {
|
||||
private var mBinding: T? = null
|
||||
|
||||
abstract fun onCreateBinding(inflater: LayoutInflater): T
|
||||
abstract fun onBindingCreated(binding: T, savedInstanceState: Bundle?)
|
||||
abstract fun onDestroyBinding(binding: T)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val binding = onCreateBinding(inflater).also { mBinding = it }
|
||||
onBindingCreated(binding, savedInstanceState)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
onDestroyBinding(requireBinding())
|
||||
mBinding = null
|
||||
}
|
||||
|
||||
protected val binding: T?
|
||||
get() = mBinding
|
||||
|
||||
protected fun requireBinding(): T {
|
||||
return requireNotNull(mBinding) {
|
||||
"ViewBinding was not available, as the fragment is not in a valid state"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,22 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
<variable
|
||||
name="playbackModel"
|
||||
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
|
||||
|
||||
<variable
|
||||
name="detailModel"
|
||||
type="org.oxycblt.auxio.detail.DetailViewModel" />
|
||||
</data>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -31,16 +15,14 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:menu="@menu/menu_playback"
|
||||
tools:subtitle="@string/lbl_all_songs"
|
||||
app:title="@string/lbl_playback" />
|
||||
app:title="@string/lbl_playback"
|
||||
tools:subtitle="@string/lbl_all_songs" />
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginTop="@dimen/spacing_mid_large"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
|
||||
|
@ -53,8 +35,8 @@
|
|||
android:id="@+id/playback_song_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
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_constraintHorizontal_bias="0.5"
|
||||
|
@ -67,8 +49,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Primary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song)}"
|
||||
android:text="@{song.resolvedName}"
|
||||
tools:text="Song Name" />
|
||||
|
||||
</FrameLayout>
|
||||
|
@ -78,10 +58,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}"
|
||||
android:text="@{song.resolvedArtistName}"
|
||||
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_constraintHorizontal_bias="0.5"
|
||||
|
@ -94,10 +72,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
|
@ -105,19 +81,45 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/playback_artist"
|
||||
tools:text="Album Name" />
|
||||
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackSeekBar
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginEnd="-16dp"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_cover"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:thumbRadius="@dimen/slider_thumb_radius" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="16:16" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
android:id="@+id/playback_loop"
|
||||
|
@ -125,7 +127,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_change_loop"
|
||||
android:onClick="@{() -> playbackModel.incrementLoopStatus()}"
|
||||
android:src="@drawable/ic_loop"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||
|
@ -150,13 +151,11 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/desc_play_pause"
|
||||
android:onClick="@{() -> playbackModel.invertPlayingStatus()}"
|
||||
android:src="@drawable/sel_playing_state"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
android:layout_marginBottom="@dimen/spacing_mid_large"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
tools:src="@drawable/ic_play" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
|
@ -164,7 +163,6 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/desc_skip_next"
|
||||
android:onClick="@{() -> playbackModel.skipNext()}"
|
||||
android:src="@drawable/ic_skip_next"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
||||
|
@ -175,9 +173,8 @@
|
|||
android:id="@+id/playback_shuffle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_song_container"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
|
@ -66,8 +64,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Primary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song)}"
|
||||
android:text="@{song.resolvedName}"
|
||||
tools:text="Song Name" />
|
||||
|
||||
</FrameLayout>
|
||||
|
@ -77,8 +73,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}"
|
||||
android:text="@{song.resolvedArtistName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_song_container"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
|
||||
|
@ -91,8 +85,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_song_container"
|
||||
|
@ -100,17 +92,48 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/playback_artist"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackSeekBar
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginEnd="-16dp"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_song_container"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_album" />
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_album"
|
||||
app:thumbRadius="@dimen/slider_thumb_radius" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="16:16" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
android:id="@+id/playback_loop"
|
||||
|
@ -118,7 +141,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_change_loop"
|
||||
android:onClick="@{() -> playbackModel.incrementLoopStatus()}"
|
||||
android:src="@drawable/ic_loop"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||
|
@ -132,7 +154,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_skip_prev"
|
||||
android:onClick="@{() -> playbackModel.skipPrev()}"
|
||||
android:src="@drawable/ic_skip_prev"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||
|
@ -144,7 +165,6 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/desc_play_pause"
|
||||
android:onClick="@{() -> playbackModel.invertPlayingStatus()}"
|
||||
android:src="@drawable/sel_playing_state"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
|
@ -158,7 +178,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_skip_next"
|
||||
android:onClick="@{() -> playbackModel.skipNext()}"
|
||||
android:src="@drawable/ic_skip_next"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||
|
@ -171,7 +190,6 @@
|
|||
android:layout_marginStart="@dimen/spacing_large"
|
||||
app:hasIndicator="true"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
||||
|
|
|
@ -4,22 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
<variable
|
||||
name="playbackModel"
|
||||
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
|
||||
|
||||
<variable
|
||||
name="detailModel"
|
||||
type="org.oxycblt.auxio.detail.DetailViewModel" />
|
||||
</data>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -38,8 +22,6 @@
|
|||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_large"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_song"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -53,8 +35,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song)}"
|
||||
android:text="@{song.resolvedName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_artist"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -68,8 +48,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}"
|
||||
android:text="@{song.resolvedArtistName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -82,22 +60,52 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackSeekBar
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:thumbRadius="@dimen/slider_thumb_radius" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="16:16" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
android:id="@+id/playback_loop"
|
||||
|
@ -105,7 +113,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_change_loop"
|
||||
android:onClick="@{() -> playbackModel.incrementLoopStatus()}"
|
||||
android:src="@drawable/ic_loop"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||
|
@ -119,7 +126,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_skip_prev"
|
||||
android:onClick="@{() -> playbackModel.skipPrev()}"
|
||||
android:src="@drawable/ic_skip_prev"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||
|
@ -132,7 +138,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_play_pause"
|
||||
android:onClick="@{() -> playbackModel.invertPlayingStatus()}"
|
||||
android:src="@drawable/sel_playing_state"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
|
@ -145,7 +150,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_skip_next"
|
||||
android:onClick="@{() -> playbackModel.skipNext()}"
|
||||
android:src="@drawable/ic_skip_next"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||
|
@ -157,7 +161,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
|
|
|
@ -4,14 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -21,8 +13,6 @@
|
|||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -35,7 +25,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
||||
|
@ -52,7 +41,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:ellipsize="end"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
|
@ -101,7 +89,6 @@
|
|||
android:id="@+id/playback_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="@{(int) song.seconds}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -51,8 +51,8 @@
|
|||
android:id="@+id/playback_song_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
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_constraintHorizontal_bias="0.5"
|
||||
|
@ -76,8 +76,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}"
|
||||
android:text="@{song.resolvedArtistName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_album"
|
||||
|
@ -92,8 +92,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||
|
@ -103,17 +103,46 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/playback_artist"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackSeekBar
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_album" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_album"
|
||||
app:thumbRadius="@dimen/slider_thumb_radius" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="16:16" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
android:id="@+id/playback_loop"
|
||||
|
|
|
@ -4,14 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -21,8 +13,6 @@
|
|||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -34,7 +24,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
||||
|
@ -50,7 +39,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:ellipsize="end"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
|
@ -99,7 +87,7 @@
|
|||
android:id="@+id/playback_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="@{(int) song.seconds}"
|
||||
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -4,14 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -21,8 +13,6 @@
|
|||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -35,7 +25,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
android:text="@{song.resolvedName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
|
@ -51,7 +40,6 @@
|
|||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
android:ellipsize="end"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
|
@ -73,7 +61,6 @@
|
|||
android:id="@+id/playback_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="@{(int) song.seconds}"
|
||||
app:trackColor="?attr/colorPrimary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
@ -4,21 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
|
||||
<variable
|
||||
name="playbackModel"
|
||||
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
|
||||
|
||||
<variable
|
||||
name="detailModel"
|
||||
type="org.oxycblt.auxio.detail.DetailViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -36,11 +21,9 @@
|
|||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_song"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
|
||||
tools:src="@drawable/ic_album" />
|
||||
|
@ -50,10 +33,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Primary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song)}"
|
||||
android:text="@{song.resolvedName}"
|
||||
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"
|
||||
|
@ -65,10 +46,8 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}"
|
||||
android:text="@{song.resolvedArtistName}"
|
||||
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"
|
||||
|
@ -79,24 +58,52 @@
|
|||
style="@style/Widget.Auxio.TextView.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||
android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackSeekBar
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_small"
|
||||
android:layout_marginEnd="@dimen/spacing_small"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:thumbRadius="@dimen/slider_thumb_radius" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
tools:text="16:16" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
android:id="@+id/playback_loop"
|
||||
|
@ -104,7 +111,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_change_loop"
|
||||
android:onClick="@{() -> playbackModel.incrementLoopStatus()}"
|
||||
android:src="@drawable/ic_loop"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||
|
@ -116,7 +122,6 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/desc_skip_prev"
|
||||
android:onClick="@{() -> playbackModel.skipPrev()}"
|
||||
android:src="@drawable/ic_skip_prev"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||
|
@ -128,9 +133,8 @@
|
|||
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_mid_large"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_play_pause"
|
||||
android:onClick="@{() -> playbackModel.invertPlayingStatus()}"
|
||||
android:src="@drawable/sel_playing_state"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||
|
@ -144,7 +148,6 @@
|
|||
android:minHeight="@dimen/size_btn_small"
|
||||
android:minWidth="@dimen/size_btn_small"
|
||||
android:contentDescription="@string/desc_skip_next"
|
||||
android:onClick="@{() -> playbackModel.skipNext()}"
|
||||
android:src="@drawable/ic_skip_next"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
||||
|
@ -159,7 +162,6 @@
|
|||
android:minWidth="@dimen/size_btn_small"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:hasIndicator="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_duration_current"
|
||||
android:id="@+id/playback_seconds"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
|
@ -38,7 +38,7 @@
|
|||
tools:text="11:38" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playback_song_duration"
|
||||
android:id="@+id/playback_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
<dimen name="spacing_mid_large">24dp</dimen>
|
||||
<dimen name="spacing_large">32dp</dimen>
|
||||
|
||||
<dimen name="spacing_small_inv">-8dp</dimen>
|
||||
|
||||
<!-- Size Namespace | Width & Heights for UI elements -->
|
||||
<dimen name="size_btn_small">48dp</dimen>
|
||||
<dimen name="size_btn_large">64dp</dimen>
|
||||
|
|
Loading…
Reference in a new issue