ui: rework custom ui components
Refactor the package structure and implementation of custom UI components.
This commit is contained in:
parent
61839405ce
commit
2d7dbd19cd
65 changed files with 342 additions and 324 deletions
|
@ -6,6 +6,10 @@
|
||||||
- Added disc number support
|
- Added disc number support
|
||||||
- Added ReplayGain support for below-reference volume tracks [i.e positive ReplayGain values]
|
- Added ReplayGain support for below-reference volume tracks [i.e positive ReplayGain values]
|
||||||
- About screen now shows counts for multiple types of library items, alongside a total duration
|
- About screen now shows counts for multiple types of library items, alongside a total duration
|
||||||
|
- New disc, track, song count, and duration sorting modes
|
||||||
|
|
||||||
|
### What's Improved
|
||||||
|
- The tab selector now hides itself when there is only one tab
|
||||||
|
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
- Fixed incorrect ellipsizing on song items
|
- Fixed incorrect ellipsizing on song items
|
||||||
|
|
|
@ -21,11 +21,11 @@ import android.app.Application
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
import coil.request.CachePolicy
|
import coil.request.CachePolicy
|
||||||
import org.oxycblt.auxio.coil.AlbumArtFetcher
|
import org.oxycblt.auxio.image.AlbumArtFetcher
|
||||||
import org.oxycblt.auxio.coil.ArtistImageFetcher
|
import org.oxycblt.auxio.image.ArtistImageFetcher
|
||||||
import org.oxycblt.auxio.coil.CrossfadeFactory
|
import org.oxycblt.auxio.image.CrossfadeFactory
|
||||||
import org.oxycblt.auxio.coil.GenreImageFetcher
|
import org.oxycblt.auxio.image.GenreImageFetcher
|
||||||
import org.oxycblt.auxio.coil.MusicKeyer
|
import org.oxycblt.auxio.image.MusicKeyer
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
|
|
|
@ -42,13 +42,11 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
*
|
*
|
||||||
* TODO: Custom language support
|
* TODO: Custom language support
|
||||||
*
|
*
|
||||||
* TODO: Rework menus [perhaps add multi-select]
|
|
||||||
*
|
|
||||||
* TODO: Rework some fragments to use listeners *even more*
|
|
||||||
*
|
|
||||||
* TODO: Fix how selection works in the RecyclerViews (doing it poorly right now)
|
* TODO: Fix how selection works in the RecyclerViews (doing it poorly right now)
|
||||||
*
|
*
|
||||||
* TODO: Rework padding ethos
|
* TODO: Rework padding ethos
|
||||||
|
*
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val playbackModel: PlaybackViewModel by viewModels()
|
private val playbackModel: PlaybackViewModel by viewModels()
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.coil
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Matrix
|
|
||||||
import android.graphics.RectF
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.annotation.AttrRes
|
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import coil.dispose
|
|
||||||
import coil.load
|
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
|
||||||
import kotlin.math.min
|
|
||||||
import org.oxycblt.auxio.R
|
|
||||||
import org.oxycblt.auxio.music.Album
|
|
||||||
import org.oxycblt.auxio.music.Artist
|
|
||||||
import org.oxycblt.auxio.music.Genre
|
|
||||||
import org.oxycblt.auxio.music.Music
|
|
||||||
import org.oxycblt.auxio.music.Song
|
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
|
||||||
import org.oxycblt.auxio.util.getColorStateListSafe
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An [AppCompatImageView] that applies many of the stylistic choices that Auxio uses regarding
|
|
||||||
* images.
|
|
||||||
*/
|
|
||||||
class StyledImageView
|
|
||||||
@JvmOverloads
|
|
||||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
|
||||||
AppCompatImageView(context, attrs, defStyleAttr) {
|
|
||||||
private val centerMatrix = Matrix()
|
|
||||||
private val matrixSrc = RectF()
|
|
||||||
private val matrixDst = RectF()
|
|
||||||
private var cornerRadius = 0f
|
|
||||||
|
|
||||||
init {
|
|
||||||
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageView)
|
|
||||||
cornerRadius = styledAttrs.getDimension(R.styleable.StyledImageView_cornerRadius, 0f)
|
|
||||||
styledAttrs.recycle()
|
|
||||||
|
|
||||||
clipToOutline = true
|
|
||||||
background =
|
|
||||||
MaterialShapeDrawable().apply {
|
|
||||||
fillColor = context.getColorStateListSafe(R.color.sel_cover_bg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
|
||||||
super.onAttachedToWindow()
|
|
||||||
|
|
||||||
// Use clipToOutline and a background drawable to crop images. While Coil's transformation
|
|
||||||
// could theoretically be used to round corners, the corner radius is dependent on the
|
|
||||||
// dimensions of the image, which will result in inconsistent corners across different
|
|
||||||
// album covers unless we resize all covers to be the same size. clipToOutline is both
|
|
||||||
// cheaper and more elegant.
|
|
||||||
if (!isInEditMode) {
|
|
||||||
val settingsManager = SettingsManager.getInstance()
|
|
||||||
if (settingsManager.roundCovers) {
|
|
||||||
(background as MaterialShapeDrawable).setCornerSize(cornerRadius)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
||||||
|
|
||||||
// Scale the image down to half-size
|
|
||||||
imageMatrix =
|
|
||||||
centerMatrix.apply {
|
|
||||||
reset()
|
|
||||||
drawable?.let { drawable ->
|
|
||||||
// Android is too good to allow us to set a fixed image size, so we instead need
|
|
||||||
// to define a matrix to scale an image directly.
|
|
||||||
|
|
||||||
// First scale the icon up to the desired size.
|
|
||||||
val iconSize = min(measuredWidth, measuredHeight) / 2f
|
|
||||||
matrixSrc.set(
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
drawable.intrinsicWidth.toFloat(),
|
|
||||||
drawable.intrinsicHeight.toFloat())
|
|
||||||
matrixDst.set(0f, 0f, iconSize, iconSize)
|
|
||||||
centerMatrix.setRectToRect(matrixSrc, matrixDst, Matrix.ScaleToFit.CENTER)
|
|
||||||
|
|
||||||
// Then actually center it into the icon, which the previous call does not
|
|
||||||
// actually do.
|
|
||||||
centerMatrix.postTranslate(
|
|
||||||
(measuredWidth - iconSize) / 2f, (measuredHeight - iconSize) / 2f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Borg the extension methods into the view
|
|
||||||
|
|
||||||
/** Bind the album cover for a [song]. */
|
|
||||||
fun StyledImageView.bindAlbumCover(song: Song) =
|
|
||||||
load(song, R.drawable.ic_song, R.string.desc_album_cover)
|
|
||||||
|
|
||||||
/** Bind the album cover for an [album]. */
|
|
||||||
fun StyledImageView.bindAlbumCover(album: Album) =
|
|
||||||
load(album, R.drawable.ic_album, R.string.desc_album_cover)
|
|
||||||
|
|
||||||
/** Bind the image for an [artist] */
|
|
||||||
fun StyledImageView.bindArtistImage(artist: Artist) =
|
|
||||||
load(artist, R.drawable.ic_artist, R.string.desc_artist_image)
|
|
||||||
|
|
||||||
/** Bind the image for a [genre] */
|
|
||||||
fun StyledImageView.bindGenreImage(genre: Genre) =
|
|
||||||
load(genre, R.drawable.ic_genre, R.string.desc_genre_image)
|
|
||||||
|
|
||||||
private fun <T : Music> StyledImageView.load(
|
|
||||||
music: T,
|
|
||||||
@DrawableRes error: Int,
|
|
||||||
@StringRes desc: Int
|
|
||||||
) {
|
|
||||||
contentDescription = context.getString(desc, music.resolveName(context))
|
|
||||||
dispose()
|
|
||||||
load(music) {
|
|
||||||
error(error)
|
|
||||||
transformations(SquareFrameTransform.INSTANCE)
|
|
||||||
listener(
|
|
||||||
onSuccess = { _, _ ->
|
|
||||||
// Using the matrix scale type will shrink the cover images, so set it back to
|
|
||||||
// the default scale type.
|
|
||||||
scaleType = ImageView.ScaleType.FIT_CENTER
|
|
||||||
},
|
|
||||||
onError = { _, _ ->
|
|
||||||
// Error icons need to be scaled correctly, so set it to the custom matrix
|
|
||||||
// that the ImageView applies
|
|
||||||
scaleType = ImageView.ScaleType.MATRIX
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,7 +22,6 @@ import androidx.core.view.isInvisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemDiscHeaderBinding
|
import org.oxycblt.auxio.databinding.ItemDiscHeaderBinding
|
||||||
|
@ -123,7 +122,7 @@ private class AlbumDetailViewHolder private constructor(private val binding: Ite
|
||||||
BindingViewHolder<Album, AlbumDetailAdapter.Listener>(binding.root) {
|
BindingViewHolder<Album, AlbumDetailAdapter.Listener>(binding.root) {
|
||||||
|
|
||||||
override fun bind(item: Album, listener: AlbumDetailAdapter.Listener) {
|
override fun bind(item: Album, listener: AlbumDetailAdapter.Listener) {
|
||||||
binding.detailCover.bindAlbumCover(item)
|
binding.detailCover.bind(item)
|
||||||
binding.detailName.textSafe = item.resolveName(binding.context)
|
binding.detailName.textSafe = item.resolveName(binding.context)
|
||||||
|
|
||||||
binding.detailSubhead.apply {
|
binding.detailSubhead.apply {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import android.content.Context
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.coil.bindArtistImage
|
|
||||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemParentBinding
|
import org.oxycblt.auxio.databinding.ItemParentBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||||
|
@ -139,7 +137,7 @@ private class ArtistDetailViewHolder private constructor(private val binding: It
|
||||||
BindingViewHolder<Artist, DetailAdapter.Listener>(binding.root) {
|
BindingViewHolder<Artist, DetailAdapter.Listener>(binding.root) {
|
||||||
|
|
||||||
override fun bind(item: Artist, listener: DetailAdapter.Listener) {
|
override fun bind(item: Artist, listener: DetailAdapter.Listener) {
|
||||||
binding.detailCover.bindArtistImage(item)
|
binding.detailCover.bind(item)
|
||||||
binding.detailName.textSafe = item.resolveName(binding.context)
|
binding.detailName.textSafe = item.resolveName(binding.context)
|
||||||
|
|
||||||
// Get the genre that corresponds to the most songs in this artist, which would be
|
// Get the genre that corresponds to the most songs in this artist, which would be
|
||||||
|
@ -181,7 +179,7 @@ private constructor(
|
||||||
private val binding: ItemParentBinding,
|
private val binding: ItemParentBinding,
|
||||||
) : BindingViewHolder<Album, MenuItemListener>(binding.root), Highlightable {
|
) : BindingViewHolder<Album, MenuItemListener>(binding.root), Highlightable {
|
||||||
override fun bind(item: Album, listener: MenuItemListener) {
|
override fun bind(item: Album, listener: MenuItemListener) {
|
||||||
binding.parentImage.bindAlbumCover(item)
|
binding.parentImage.bind(item)
|
||||||
binding.parentName.textSafe = item.resolveName(binding.context)
|
binding.parentName.textSafe = item.resolveName(binding.context)
|
||||||
binding.parentInfo.textSafe =
|
binding.parentInfo.textSafe =
|
||||||
if (item.year != null) {
|
if (item.year != null) {
|
||||||
|
@ -226,7 +224,7 @@ private constructor(
|
||||||
private val binding: ItemSongBinding,
|
private val binding: ItemSongBinding,
|
||||||
) : BindingViewHolder<Song, MenuItemListener>(binding.root), Highlightable {
|
) : BindingViewHolder<Song, MenuItemListener>(binding.root), Highlightable {
|
||||||
override fun bind(item: Song, listener: MenuItemListener) {
|
override fun bind(item: Song, listener: MenuItemListener) {
|
||||||
binding.songAlbumCover.bindAlbumCover(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.textSafe = item.resolveName(binding.context)
|
binding.songName.textSafe = item.resolveName(binding.context)
|
||||||
binding.songInfo.textSafe = item.album.resolveName(binding.context)
|
binding.songInfo.textSafe = item.album.resolveName(binding.context)
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,6 @@ import android.content.Context
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.coil.bindGenreImage
|
|
||||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||||
import org.oxycblt.auxio.music.Genre
|
import org.oxycblt.auxio.music.Genre
|
||||||
|
@ -114,7 +112,7 @@ class GenreDetailAdapter(listener: Listener) :
|
||||||
private class GenreDetailViewHolder private constructor(private val binding: ItemDetailBinding) :
|
private class GenreDetailViewHolder private constructor(private val binding: ItemDetailBinding) :
|
||||||
BindingViewHolder<Genre, DetailAdapter.Listener>(binding.root) {
|
BindingViewHolder<Genre, DetailAdapter.Listener>(binding.root) {
|
||||||
override fun bind(item: Genre, listener: DetailAdapter.Listener) {
|
override fun bind(item: Genre, listener: DetailAdapter.Listener) {
|
||||||
binding.detailCover.bindGenreImage(item)
|
binding.detailCover.bind(item)
|
||||||
binding.detailName.textSafe = item.resolveName(binding.context)
|
binding.detailName.textSafe = item.resolveName(binding.context)
|
||||||
binding.detailSubhead.textSafe =
|
binding.detailSubhead.textSafe =
|
||||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, item.songs.size)
|
binding.context.getPluralSafe(R.plurals.fmt_song_count, item.songs.size)
|
||||||
|
@ -146,7 +144,7 @@ private class GenreDetailViewHolder private constructor(private val binding: Ite
|
||||||
class GenreSongViewHolder private constructor(private val binding: ItemSongBinding) :
|
class GenreSongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
BindingViewHolder<Song, MenuItemListener>(binding.root), Highlightable {
|
BindingViewHolder<Song, MenuItemListener>(binding.root), Highlightable {
|
||||||
override fun bind(item: Song, listener: MenuItemListener) {
|
override fun bind(item: Song, listener: MenuItemListener) {
|
||||||
binding.songAlbumCover.bindAlbumCover(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.textSafe = item.resolveName(binding.context)
|
binding.songName.textSafe = item.resolveName(binding.context)
|
||||||
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
||||||
binding.root.apply {
|
binding.root.apply {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.coil
|
package org.oxycblt.auxio.image
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.coil
|
package org.oxycblt.auxio.image
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.coil
|
package org.oxycblt.auxio.image
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.coil
|
package org.oxycblt.auxio.image
|
||||||
|
|
||||||
import coil.decode.DataSource
|
import coil.decode.DataSource
|
||||||
import coil.drawable.CrossfadeDrawable
|
import coil.drawable.CrossfadeDrawable
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.coil
|
package org.oxycblt.auxio.image
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import coil.size.Size
|
import coil.size.Size
|
|
@ -25,7 +25,6 @@ import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding
|
import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.ui.MainNavigationAction
|
import org.oxycblt.auxio.ui.MainNavigationAction
|
||||||
|
@ -104,7 +103,7 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
|
||||||
if (song != null) {
|
if (song != null) {
|
||||||
val context = requireContext()
|
val context = requireContext()
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
binding.playbackCover.bindAlbumCover(song)
|
binding.playbackCover.bind(song)
|
||||||
binding.playbackSong.textSafe = song.resolveName(context)
|
binding.playbackSong.textSafe = song.resolveName(context)
|
||||||
binding.playbackInfo.textSafe = song.resolveIndividualArtistName(context)
|
binding.playbackInfo.textSafe = song.resolveIndividualArtistName(context)
|
||||||
binding.playbackProgressBar.max = song.durationSecs.toInt()
|
binding.playbackProgressBar.max = song.durationSecs.toInt()
|
||||||
|
|
|
@ -28,7 +28,6 @@ import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.slider.Slider
|
import com.google.android.material.slider.Slider
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
|
@ -176,7 +175,7 @@ class PlaybackPanelFragment :
|
||||||
|
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
val context = requireContext()
|
val context = requireContext()
|
||||||
binding.playbackCover.bindAlbumCover(song)
|
binding.playbackCover.bind(song)
|
||||||
binding.playbackSong.textSafe = song.resolveName(context)
|
binding.playbackSong.textSafe = song.resolveName(context)
|
||||||
binding.playbackArtist.textSafe = song.resolveIndividualArtistName(context)
|
binding.playbackArtist.textSafe = song.resolveIndividualArtistName(context)
|
||||||
binding.playbackAlbum.textSafe = song.album.resolveName(context)
|
binding.playbackAlbum.textSafe = song.album.resolveName(context)
|
||||||
|
@ -186,7 +185,7 @@ class PlaybackPanelFragment :
|
||||||
binding.playbackDuration.textSafe = seconds.formatDuration(false)
|
binding.playbackDuration.textSafe = seconds.formatDuration(false)
|
||||||
binding.playbackSeekBar.apply {
|
binding.playbackSeekBar.apply {
|
||||||
isEnabled = seconds > 0L
|
isEnabled = seconds > 0L
|
||||||
valueToSafe = max(seconds, 1L).toFloat()
|
valueTo = max(seconds, 1L).toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +199,7 @@ class PlaybackPanelFragment :
|
||||||
// around.
|
// around.
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
if (!binding.playbackPosition.isActivated) {
|
if (!binding.playbackPosition.isActivated) {
|
||||||
binding.playbackSeekBar.valueSafe = position.toFloat()
|
binding.playbackSeekBar.value = position.toFloat()
|
||||||
binding.playbackPosition.textSafe = position.formatDuration(true)
|
binding.playbackPosition.textSafe = position.formatDuration(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,26 +218,4 @@ class PlaybackPanelFragment :
|
||||||
private fun updateShuffled(isShuffled: Boolean) {
|
private fun updateShuffled(isShuffled: Boolean) {
|
||||||
requireBinding().playbackShuffle.isActivated = isShuffled
|
requireBinding().playbackShuffle.isActivated = isShuffled
|
||||||
}
|
}
|
||||||
|
|
||||||
private var Slider.valueSafe: Float
|
|
||||||
get() = value
|
|
||||||
set(v) {
|
|
||||||
value =
|
|
||||||
if (v > valueTo) {
|
|
||||||
valueTo
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var Slider.valueToSafe: Float
|
|
||||||
get() = valueTo
|
|
||||||
set(v) {
|
|
||||||
valueTo =
|
|
||||||
if (value > v) {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.ui.BackingData
|
import org.oxycblt.auxio.ui.BackingData
|
||||||
|
@ -71,7 +70,7 @@ private constructor(
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun bind(item: Song, listener: QueueItemListener) {
|
override fun bind(item: Song, listener: QueueItemListener) {
|
||||||
binding.songAlbumCover.bindAlbumCover(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.textSafe = item.resolveName(binding.context)
|
binding.songName.textSafe = item.resolveName(binding.context)
|
||||||
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import android.support.v4.media.MediaMetadataCompat
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import android.support.v4.media.session.PlaybackStateCompat
|
import android.support.v4.media.session.PlaybackStateCompat
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
import org.oxycblt.auxio.coil.BitmapProvider
|
import org.oxycblt.auxio.image.BitmapProvider
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
|
|
@ -30,7 +30,7 @@ import androidx.media.app.NotificationCompat.MediaStyle
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.BitmapProvider
|
import org.oxycblt.auxio.image.BitmapProvider
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.RepeatMode
|
import org.oxycblt.auxio.playback.state.RepeatMode
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.oxycblt.auxio.settings
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import org.oxycblt.auxio.accent.Accent
|
import org.oxycblt.auxio.ui.accent.Accent
|
||||||
|
|
||||||
// A couple of utils for migrating from old settings values to the new formats
|
// A couple of utils for migrating from old settings values to the new formats
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,12 @@ import androidx.preference.children
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.Coil
|
import coil.Coil
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.accent.AccentCustomizeDialog
|
|
||||||
import org.oxycblt.auxio.home.tabs.TabCustomizeDialog
|
import org.oxycblt.auxio.home.tabs.TabCustomizeDialog
|
||||||
import org.oxycblt.auxio.music.excluded.ExcludedDialog
|
import org.oxycblt.auxio.music.excluded.ExcludedDialog
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.settings.pref.IntListPreference
|
import org.oxycblt.auxio.settings.pref.IntListPreference
|
||||||
import org.oxycblt.auxio.settings.pref.IntListPreferenceDialog
|
import org.oxycblt.auxio.settings.pref.IntListPreferenceDialog
|
||||||
|
import org.oxycblt.auxio.ui.accent.AccentCustomizeDialog
|
||||||
import org.oxycblt.auxio.util.hardRestart
|
import org.oxycblt.auxio.util.hardRestart
|
||||||
import org.oxycblt.auxio.util.isNight
|
import org.oxycblt.auxio.util.isNight
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
|
|
@ -22,12 +22,12 @@ import android.content.SharedPreferences
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import org.oxycblt.auxio.accent.Accent
|
|
||||||
import org.oxycblt.auxio.home.tabs.Tab
|
import org.oxycblt.auxio.home.tabs.Tab
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.playback.system.ReplayGainMode
|
import org.oxycblt.auxio.playback.system.ReplayGainMode
|
||||||
import org.oxycblt.auxio.ui.DisplayMode
|
import org.oxycblt.auxio.ui.DisplayMode
|
||||||
import org.oxycblt.auxio.ui.Sort
|
import org.oxycblt.auxio.ui.Sort
|
||||||
|
import org.oxycblt.auxio.ui.accent.Accent
|
||||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,10 +32,11 @@ constructor(
|
||||||
defStyleAttr: Int = androidx.preference.R.attr.dialogPreferenceStyle,
|
defStyleAttr: Int = androidx.preference.R.attr.dialogPreferenceStyle,
|
||||||
defStyleRes: Int = 0
|
defStyleRes: Int = 0
|
||||||
) : DialogPreference(context, attrs, defStyleAttr, defStyleRes) {
|
) : DialogPreference(context, attrs, defStyleAttr, defStyleRes) {
|
||||||
// Reflect into Preference to get the (normally inaccessible) default value.
|
|
||||||
val entries: Array<CharSequence>
|
val entries: Array<CharSequence>
|
||||||
val values: IntArray
|
val values: IntArray
|
||||||
private var currentValue: Int? = null
|
private var currentValue: Int? = null
|
||||||
|
|
||||||
|
// Reflect into Preference to get the (normally inaccessible) default value.
|
||||||
private val defValue: Int
|
private val defValue: Int
|
||||||
get() = defValueField.get(this) as Int
|
get() = defValueField.get(this) as Int
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.oxycblt.auxio.util.getDrawableSafe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [SwitchPreferenceCompat] that emulates the M3 switches until the design team actually bothers
|
* A [SwitchPreferenceCompat] that emulates the M3 switches until the design team actually bothers
|
||||||
* to add them to MDC.
|
* to add them to MDC TODO: Remove this once MaterialSwitch is stabilized.
|
||||||
*/
|
*/
|
||||||
class M3SwitchPreference
|
class M3SwitchPreference
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
@ -45,7 +45,6 @@ constructor(
|
||||||
// Lollipop cannot into ColorStateList, disable this feature on that version
|
// Lollipop cannot into ColorStateList, disable this feature on that version
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
val switch = holder.findViewById(androidx.preference.R.id.switchWidget)
|
val switch = holder.findViewById(androidx.preference.R.id.switchWidget)
|
||||||
|
|
||||||
if (switch is SwitchCompat) {
|
if (switch is SwitchCompat) {
|
||||||
switch.apply {
|
switch.apply {
|
||||||
trackDrawable = context.getDrawableSafe(R.drawable.ui_m3_switch_track)
|
trackDrawable = context.getDrawableSafe(R.drawable.ui_m3_switch_track)
|
||||||
|
|
|
@ -54,11 +54,9 @@ fun Fragment.newMenu(anchor: View, data: Item, flag: Int = ActionMenu.FLAG_NONE)
|
||||||
* @throws IllegalStateException When there is no menu for this specific datatype/flag
|
* @throws IllegalStateException When there is no menu for this specific datatype/flag
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*
|
*
|
||||||
* TODO: Stop scrolling when a menu is open
|
|
||||||
*
|
|
||||||
* TODO: Prevent duplicate menus from showing up
|
* TODO: Prevent duplicate menus from showing up
|
||||||
*
|
*
|
||||||
* TODO: Maybe replace this with a bottom sheet?
|
* TODO: Add multi-select
|
||||||
*/
|
*/
|
||||||
class ActionMenu(
|
class ActionMenu(
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
|
|
|
@ -22,7 +22,10 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import org.oxycblt.auxio.music.Music
|
import org.oxycblt.auxio.music.Music
|
||||||
|
|
||||||
/** A ViewModel that handles complicated navigation situations. */
|
/**
|
||||||
|
* A ViewModel that handles complicated navigation situations.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class NavigationViewModel : ViewModel() {
|
class NavigationViewModel : ViewModel() {
|
||||||
private val _mainNavigationAction = MutableLiveData<MainNavigationAction?>()
|
private val _mainNavigationAction = MutableLiveData<MainNavigationAction?>()
|
||||||
/** Flag for main fragment navigation. Intended for MainFragment use only. */
|
/** Flag for main fragment navigation. Intended for MainFragment use only. */
|
||||||
|
|
|
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
/**
|
/**
|
||||||
* An adapter for one viewholder tied to one type of data. All functionality is derived from the
|
* An adapter for one viewholder tied to one type of data. All functionality is derived from the
|
||||||
* overridden values.
|
* overridden values.
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class MonoAdapter<T, L, VH : BindingViewHolder<T, L>>(private val listener: L) :
|
abstract class MonoAdapter<T, L, VH : BindingViewHolder<T, L>>(private val listener: L) :
|
||||||
RecyclerView.Adapter<VH>() {
|
RecyclerView.Adapter<VH>() {
|
||||||
|
@ -51,6 +52,7 @@ private typealias AnyCreator = BindingViewHolder.Creator<out RecyclerView.ViewHo
|
||||||
/**
|
/**
|
||||||
* An adapter for many viewholders tied to many types of data. Deriving this is more complicated
|
* An adapter for many viewholders tied to many types of data. Deriving this is more complicated
|
||||||
* than [MonoAdapter], as less overrides can be provided "for free".
|
* than [MonoAdapter], as less overrides can be provided "for free".
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class MultiAdapter<L>(private val listener: L) :
|
abstract class MultiAdapter<L>(private val listener: L) :
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
@ -99,6 +101,7 @@ abstract class MultiAdapter<L>(private val listener: L) :
|
||||||
* A variation of [RecyclerView.ViewHolder] that enables ViewBinding. This is be used to provide a
|
* A variation of [RecyclerView.ViewHolder] that enables ViewBinding. This is be used to provide a
|
||||||
* universal surface for binding data to a ViewHolder, and can be used with [MonoAdapter] to get an
|
* universal surface for binding data to a ViewHolder, and can be used with [MonoAdapter] to get an
|
||||||
* entire adapter implementation for free.
|
* entire adapter implementation for free.
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
abstract class BindingViewHolder<T, L>(root: View) : RecyclerView.ViewHolder(root) {
|
abstract class BindingViewHolder<T, L>(root: View) : RecyclerView.ViewHolder(root) {
|
||||||
abstract fun bind(item: T, listener: L)
|
abstract fun bind(item: T, listener: L)
|
||||||
|
@ -159,6 +162,7 @@ abstract class BackingData<T> {
|
||||||
/**
|
/**
|
||||||
* A list-backed [BackingData] that is modified using adapter primitives. Useful in cases where
|
* A list-backed [BackingData] that is modified using adapter primitives. Useful in cases where
|
||||||
* [AsyncBackingData] is not preferable due to bugs involving diffing.
|
* [AsyncBackingData] is not preferable due to bugs involving diffing.
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class PrimitiveBackingData<T>(private val adapter: RecyclerView.Adapter<*>) : BackingData<T>() {
|
class PrimitiveBackingData<T>(private val adapter: RecyclerView.Adapter<*>) : BackingData<T>() {
|
||||||
private var _currentList = mutableListOf<T>()
|
private var _currentList = mutableListOf<T>()
|
||||||
|
@ -184,6 +188,7 @@ class PrimitiveBackingData<T>(private val adapter: RecyclerView.Adapter<*>) : Ba
|
||||||
* A list-backed [BackingData] that is modified with [AsyncListDiffer]. This is useful in cases
|
* A list-backed [BackingData] that is modified with [AsyncListDiffer]. This is useful in cases
|
||||||
* where data updates are rapid-fire and unpredictable, and where the benefits of asynchronously
|
* where data updates are rapid-fire and unpredictable, and where the benefits of asynchronously
|
||||||
* diffing the adapter outweigh the shortcomings.
|
* diffing the adapter outweigh the shortcomings.
|
||||||
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class AsyncBackingData<T>(
|
class AsyncBackingData<T>(
|
||||||
adapter: RecyclerView.Adapter<*>,
|
adapter: RecyclerView.Adapter<*>,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.ui
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
|
@ -29,33 +29,33 @@ import org.oxycblt.auxio.util.getDimenSizeSafe
|
||||||
import org.oxycblt.auxio.util.getDrawableSafe
|
import org.oxycblt.auxio.util.getDrawableSafe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An [AppCompatImageButton] designed for the buttons used in the playback display.
|
* An [AppCompatImageButton] that applies many of the stylistic choices that Auxio uses regarding
|
||||||
|
* buttons.
|
||||||
*
|
*
|
||||||
* Auxio's playback buttons have never followed the typical 24dp icon size that all other UI
|
* More specifically, this class add two features:
|
||||||
* elements do, mostly because those icons just look bad at that size with all the gobs of
|
* - Specification of the icon size. This is to accommodate the playback buttons, which tend to be
|
||||||
* whitespace surrounding them. So, this view resizes the icons to a fixed 32dp in a way that
|
* larger as by default the playback icons look terrible with the gobs of whitespace everywhere.
|
||||||
* doesn't require a whole new icon set.
|
* - Addition of an indicator, which is a dot that can denote when a button is active. This is
|
||||||
*
|
* also useful for the playback buttons, as at times highlighting them is not enough to
|
||||||
* This view also enables use of an "indicator", which is a dot that can denote when a button is
|
* differentiate them.
|
||||||
* active. This is useful for the shuffle/repeat buttons, as at times highlighting them is not
|
* @author OxygenCobalt
|
||||||
* enough to differentiate them.
|
|
||||||
*/
|
*/
|
||||||
class PlaybackButton
|
class StyledImageButton
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||||
AppCompatImageButton(context, attrs, defStyleAttr) {
|
AppCompatImageButton(context, attrs, defStyleAttr) {
|
||||||
private val iconSize = context.getDimenSizeSafe(R.dimen.size_playback_icon)
|
private val iconSize: Int
|
||||||
private val centerMatrix = Matrix()
|
|
||||||
private val matrixSrc = RectF()
|
|
||||||
private val matrixDst = RectF()
|
|
||||||
|
|
||||||
private val indicatorDrawable = context.getDrawableSafe(R.drawable.ui_indicator)
|
|
||||||
private var hasIndicator = false
|
private var hasIndicator = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val centerMatrix = Matrix()
|
||||||
|
private val matrixSrc = RectF()
|
||||||
|
private val matrixDst = RectF()
|
||||||
|
private val indicatorDrawable = context.getDrawableSafe(R.drawable.ui_indicator)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val size = context.getDimenSizeSafe(R.dimen.size_btn_small)
|
val size = context.getDimenSizeSafe(R.dimen.size_btn_small)
|
||||||
minimumWidth = size
|
minimumWidth = size
|
||||||
|
@ -63,14 +63,22 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
scaleType = ScaleType.MATRIX
|
scaleType = ScaleType.MATRIX
|
||||||
setBackgroundResource(R.drawable.ui_large_unbounded_ripple)
|
setBackgroundResource(R.drawable.ui_large_unbounded_ripple)
|
||||||
|
|
||||||
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.PlaybackButton)
|
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageButton)
|
||||||
hasIndicator = styledAttrs.getBoolean(R.styleable.PlaybackButton_hasIndicator, false)
|
iconSize =
|
||||||
|
styledAttrs
|
||||||
|
.getDimension(
|
||||||
|
R.styleable.StyledImageButton_iconSize,
|
||||||
|
context.getDimenSizeSafe(R.dimen.size_icon_normal).toFloat())
|
||||||
|
.toInt()
|
||||||
|
hasIndicator = styledAttrs.getBoolean(R.styleable.StyledImageButton_hasIndicator, false)
|
||||||
styledAttrs.recycle()
|
styledAttrs.recycle()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||||
|
|
||||||
|
// TODO: Scale this drawable based on available space after padding
|
||||||
|
|
||||||
imageMatrix =
|
imageMatrix =
|
||||||
centerMatrix.apply {
|
centerMatrix.apply {
|
||||||
reset()
|
reset()
|
140
app/src/main/java/org/oxycblt/auxio/ui/StyledImageView.kt
Normal file
140
app/src/main/java/org/oxycblt/auxio/ui/StyledImageView.kt
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* 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.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.ColorFilter
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import coil.dispose
|
||||||
|
import coil.load
|
||||||
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.image.SquareFrameTransform
|
||||||
|
import org.oxycblt.auxio.music.Album
|
||||||
|
import org.oxycblt.auxio.music.Artist
|
||||||
|
import org.oxycblt.auxio.music.Genre
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
|
import org.oxycblt.auxio.music.Song
|
||||||
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
|
import org.oxycblt.auxio.util.getColorStateListSafe
|
||||||
|
import org.oxycblt.auxio.util.getDrawableSafe
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An [AppCompatImageView] that applies many of the stylistic choices that Auxio uses regarding
|
||||||
|
* images.
|
||||||
|
*
|
||||||
|
* Default behavior includes the addition of a tonal background, automatic sizing of icons to
|
||||||
|
* half of the view size, and corner radius application depending on user preference.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
|
class StyledImageView
|
||||||
|
@JvmOverloads
|
||||||
|
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||||
|
AppCompatImageView(context, attrs, defStyleAttr) {
|
||||||
|
private var cornerRadius = 0f
|
||||||
|
|
||||||
|
init {
|
||||||
|
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageView)
|
||||||
|
|
||||||
|
cornerRadius = styledAttrs.getDimension(R.styleable.StyledImageView_cornerRadius, 0f)
|
||||||
|
|
||||||
|
styledAttrs.recycle()
|
||||||
|
|
||||||
|
clipToOutline = true
|
||||||
|
background =
|
||||||
|
MaterialShapeDrawable().apply {
|
||||||
|
fillColor = context.getColorStateListSafe(R.color.sel_cover_bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a pre-set drawable, ensure that it's half-size.
|
||||||
|
val drawable = drawable
|
||||||
|
if (drawable != null) {
|
||||||
|
setImageDrawable(HalfSizeDrawable(drawable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow()
|
||||||
|
|
||||||
|
// Use clipToOutline and a background drawable to crop images. While Coil's transformation
|
||||||
|
// could theoretically be used to round corners, the corner radius is dependent on the
|
||||||
|
// dimensions of the image, which will result in inconsistent corners across different
|
||||||
|
// album covers unless we resize all covers to be the same size. clipToOutline is both
|
||||||
|
// cheaper and more elegant.
|
||||||
|
if (!isInEditMode) {
|
||||||
|
val settingsManager = SettingsManager.getInstance()
|
||||||
|
if (settingsManager.roundCovers) {
|
||||||
|
(background as MaterialShapeDrawable).setCornerSize(cornerRadius)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bind the album cover for a [song]. */
|
||||||
|
fun bind(song: Song) = load(song, R.drawable.ic_song, R.string.desc_album_cover)
|
||||||
|
|
||||||
|
/** Bind the album cover for an [album]. */
|
||||||
|
fun bind(album: Album) = load(album, R.drawable.ic_album, R.string.desc_album_cover)
|
||||||
|
|
||||||
|
/** Bind the image for an [artist] */
|
||||||
|
fun bind(artist: Artist) = load(artist, R.drawable.ic_artist, R.string.desc_artist_image)
|
||||||
|
|
||||||
|
/** Bind the image for a [genre] */
|
||||||
|
fun bind(genre: Genre) = load(genre, R.drawable.ic_genre, R.string.desc_genre_image)
|
||||||
|
|
||||||
|
private fun <T : Music> load(music: T, @DrawableRes error: Int, @StringRes desc: Int) {
|
||||||
|
dispose()
|
||||||
|
load(music) {
|
||||||
|
error(HalfSizeDrawable(context, error))
|
||||||
|
transformations(SquareFrameTransform.INSTANCE)
|
||||||
|
}
|
||||||
|
contentDescription = context.getString(desc, music.resolveName(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HalfSizeDrawable(private val src: Drawable) : Drawable() {
|
||||||
|
constructor(context: Context, @DrawableRes res: Int) : this(context.getDrawableSafe(res))
|
||||||
|
|
||||||
|
override fun draw(canvas: Canvas) {
|
||||||
|
src.bounds.set(canvas.clipBounds)
|
||||||
|
val adjustWidth = src.bounds.width() / 4
|
||||||
|
val adjustHeight = src.bounds.height() / 4
|
||||||
|
src.bounds.set(
|
||||||
|
adjustWidth,
|
||||||
|
adjustHeight,
|
||||||
|
src.bounds.width() - adjustWidth,
|
||||||
|
src.bounds.height() - adjustHeight)
|
||||||
|
src.draw(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setAlpha(alpha: Int) {
|
||||||
|
src.alpha = alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setColorFilter(colorFilter: ColorFilter?) {
|
||||||
|
src.colorFilter = colorFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,10 @@ import androidx.viewbinding.ViewBinding
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog fragment enabling ViewBinding inflation and usage across the dialog fragment lifecycle.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
abstract class ViewBindingDialogFragment<T : ViewBinding> : DialogFragment() {
|
abstract class ViewBindingDialogFragment<T : ViewBinding> : DialogFragment() {
|
||||||
private var _binding: T? = null
|
private var _binding: T? = null
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,10 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
|
||||||
/** A fragment enabling ViewBinding inflation and usage across the fragment lifecycle. */
|
/**
|
||||||
|
* A fragment enabling ViewBinding inflation and usage across the fragment lifecycle.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
abstract class ViewBindingFragment<T : ViewBinding> : Fragment() {
|
abstract class ViewBindingFragment<T : ViewBinding> : Fragment() {
|
||||||
private var _binding: T? = null
|
private var _binding: T? = null
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,6 @@ package org.oxycblt.auxio.ui
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
|
||||||
import org.oxycblt.auxio.coil.bindArtistImage
|
|
||||||
import org.oxycblt.auxio.coil.bindGenreImage
|
|
||||||
import org.oxycblt.auxio.databinding.ItemHeaderBinding
|
import org.oxycblt.auxio.databinding.ItemHeaderBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemParentBinding
|
import org.oxycblt.auxio.databinding.ItemParentBinding
|
||||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||||
|
@ -35,11 +32,14 @@ import org.oxycblt.auxio.util.getPluralSafe
|
||||||
import org.oxycblt.auxio.util.inflater
|
import org.oxycblt.auxio.util.inflater
|
||||||
import org.oxycblt.auxio.util.textSafe
|
import org.oxycblt.auxio.util.textSafe
|
||||||
|
|
||||||
/** The shared ViewHolder for a [Song]. */
|
/**
|
||||||
|
* The shared ViewHolder for a [Song].
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
BindingViewHolder<Song, MenuItemListener>(binding.root) {
|
BindingViewHolder<Song, MenuItemListener>(binding.root) {
|
||||||
override fun bind(item: Song, listener: MenuItemListener) {
|
override fun bind(item: Song, listener: MenuItemListener) {
|
||||||
binding.songAlbumCover.bindAlbumCover(item)
|
binding.songAlbumCover.bind(item)
|
||||||
binding.songName.textSafe = item.resolveName(binding.context)
|
binding.songName.textSafe = item.resolveName(binding.context)
|
||||||
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
binding.songInfo.textSafe = item.resolveIndividualArtistName(binding.context)
|
||||||
binding.root.apply {
|
binding.root.apply {
|
||||||
|
@ -70,14 +70,17 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The Shared ViewHolder for a [Album]. */
|
/**
|
||||||
|
* The Shared ViewHolder for a [Album].
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class AlbumViewHolder
|
class AlbumViewHolder
|
||||||
private constructor(
|
private constructor(
|
||||||
private val binding: ItemParentBinding,
|
private val binding: ItemParentBinding,
|
||||||
) : BindingViewHolder<Album, MenuItemListener>(binding.root) {
|
) : BindingViewHolder<Album, MenuItemListener>(binding.root) {
|
||||||
|
|
||||||
override fun bind(item: Album, listener: MenuItemListener) {
|
override fun bind(item: Album, listener: MenuItemListener) {
|
||||||
binding.parentImage.bindAlbumCover(item)
|
binding.parentImage.bind(item)
|
||||||
binding.parentName.textSafe = item.resolveName(binding.context)
|
binding.parentName.textSafe = item.resolveName(binding.context)
|
||||||
binding.parentInfo.textSafe = item.artist.resolveName(binding.context)
|
binding.parentInfo.textSafe = item.artist.resolveName(binding.context)
|
||||||
binding.root.apply {
|
binding.root.apply {
|
||||||
|
@ -108,12 +111,15 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The Shared ViewHolder for a [Artist]. */
|
/**
|
||||||
|
* The Shared ViewHolder for a [Artist].
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class ArtistViewHolder private constructor(private val binding: ItemParentBinding) :
|
class ArtistViewHolder private constructor(private val binding: ItemParentBinding) :
|
||||||
BindingViewHolder<Artist, MenuItemListener>(binding.root) {
|
BindingViewHolder<Artist, MenuItemListener>(binding.root) {
|
||||||
|
|
||||||
override fun bind(item: Artist, listener: MenuItemListener) {
|
override fun bind(item: Artist, listener: MenuItemListener) {
|
||||||
binding.parentImage.bindArtistImage(item)
|
binding.parentImage.bind(item)
|
||||||
binding.parentName.textSafe = item.resolveName(binding.context)
|
binding.parentName.textSafe = item.resolveName(binding.context)
|
||||||
binding.parentInfo.textSafe =
|
binding.parentInfo.textSafe =
|
||||||
binding.context.getString(
|
binding.context.getString(
|
||||||
|
@ -149,14 +155,17 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The Shared ViewHolder for a [Genre]. */
|
/**
|
||||||
|
* The Shared ViewHolder for a [Genre].
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class GenreViewHolder
|
class GenreViewHolder
|
||||||
private constructor(
|
private constructor(
|
||||||
private val binding: ItemParentBinding,
|
private val binding: ItemParentBinding,
|
||||||
) : BindingViewHolder<Genre, MenuItemListener>(binding.root) {
|
) : BindingViewHolder<Genre, MenuItemListener>(binding.root) {
|
||||||
|
|
||||||
override fun bind(item: Genre, listener: MenuItemListener) {
|
override fun bind(item: Genre, listener: MenuItemListener) {
|
||||||
binding.parentImage.bindGenreImage(item)
|
binding.parentImage.bind(item)
|
||||||
binding.parentName.textSafe = item.resolveName(binding.context)
|
binding.parentName.textSafe = item.resolveName(binding.context)
|
||||||
binding.parentInfo.textSafe =
|
binding.parentInfo.textSafe =
|
||||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, item.songs.size)
|
binding.context.getPluralSafe(R.plurals.fmt_song_count, item.songs.size)
|
||||||
|
@ -187,7 +196,10 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The Shared ViewHolder for a [Header]. */
|
/**
|
||||||
|
* The Shared ViewHolder for a [Header].
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class NewHeaderViewHolder private constructor(private val binding: ItemHeaderBinding) :
|
class NewHeaderViewHolder private constructor(private val binding: ItemHeaderBinding) :
|
||||||
BindingViewHolder<Header, Unit>(binding.root) {
|
BindingViewHolder<Header, Unit>(binding.root) {
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.accent
|
package org.oxycblt.auxio.ui.accent
|
||||||
|
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.accent
|
package org.oxycblt.auxio.ui.accent
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.appcompat.widget.TooltipCompat
|
import androidx.appcompat.widget.TooltipCompat
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.accent
|
package org.oxycblt.auxio.ui.accent
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
|
@ -15,7 +15,7 @@
|
||||||
* 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.accent
|
package org.oxycblt.auxio.ui.accent
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
|
@ -26,8 +26,6 @@ import org.oxycblt.auxio.playback.system.PlaybackService
|
||||||
import org.oxycblt.auxio.util.newBroadcastIntent
|
import org.oxycblt.auxio.util.newBroadcastIntent
|
||||||
import org.oxycblt.auxio.util.newMainIntent
|
import org.oxycblt.auxio.util.newMainIntent
|
||||||
|
|
||||||
// TODO: Still need to change the default cover here
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default widget is displayed whenever there is no music playing. It just shows the message "No
|
* The default widget is displayed whenever there is no music playing. It just shows the message "No
|
||||||
* music playing".
|
* music playing".
|
||||||
|
@ -109,7 +107,7 @@ private fun RemoteViews.applyCover(
|
||||||
R.id.widget_cover,
|
R.id.widget_cover,
|
||||||
context.getString(R.string.desc_album_cover, state.song.album.resolveName(context)))
|
context.getString(R.string.desc_album_cover, state.song.album.resolveName(context)))
|
||||||
} else {
|
} else {
|
||||||
setImageViewResource(R.id.widget_cover, R.drawable.ic_widget_album)
|
setImageViewResource(R.id.widget_cover, R.drawable.ic_remote_default_cover)
|
||||||
setContentDescription(R.id.widget_cover, context.getString(R.string.desc_no_cover))
|
setContentDescription(R.id.widget_cover, context.getString(R.string.desc_no_cover))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ import coil.request.ImageRequest
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import org.oxycblt.auxio.coil.BitmapProvider
|
import org.oxycblt.auxio.image.BitmapProvider
|
||||||
import org.oxycblt.auxio.coil.SquareFrameTransform
|
import org.oxycblt.auxio.image.SquareFrameTransform
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
@ -87,7 +87,7 @@ class WidgetComponent(private val context: Context) :
|
||||||
val metrics = context.resources.displayMetrics
|
val metrics = context.resources.displayMetrics
|
||||||
|
|
||||||
// Use RoundedCornersTransformation. This is because our hack to get a 1:1
|
// Use RoundedCornersTransformation. This is because our hack to get a 1:1
|
||||||
// aspect ratio on widget ImageViews doesn't actually result in a square
|
// aspect ratio on widget ImageViews doesn't actually result in a square
|
||||||
// ImageView, so clipToOutline won't work.
|
// ImageView, so clipToOutline won't work.
|
||||||
builder
|
builder
|
||||||
.transformations(
|
.transformations(
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<!--
|
<!--
|
||||||
Special album icon where the center is filled with the surface color.
|
Special album icon where the center is filled with the surface color.
|
||||||
This is used for widgets specifically, as it creates a contiguous surface
|
|
||||||
that looks nicer on the small widgets while also lining up with the preview.
|
|
||||||
|
|
||||||
This does cause issues when the theme is changed on older android versions, but
|
We would normally use a song icon with a filled-in background, but RemoteView
|
||||||
this is tolerable.
|
limitations make that effectively impossible. Once again, the widget has to
|
||||||
|
be inconsistent with the rest of the app because google refuses to dumpster
|
||||||
|
a terrible API.
|
||||||
-->
|
-->
|
||||||
<path
|
<path
|
||||||
android:fillColor="?attr/colorPrimary"
|
android:fillColor="?attr/colorPrimary"
|
|
@ -6,7 +6,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/spacing_medium">
|
android:padding="@dimen/spacing_medium">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/detail_cover"
|
android:id="@+id/detail_cover"
|
||||||
style="@style/Widget.Auxio.Image.Huge"
|
style="@style/Widget.Auxio.Image.Huge"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
app:title="@string/lbl_playback"
|
app:title="@string/lbl_playback"
|
||||||
tools:subtitle="@string/lbl_all_songs" />
|
tools:subtitle="@string/lbl_all_songs" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
android:layout_marginStart="@dimen/spacing_medium"
|
android:layout_marginStart="@dimen/spacing_medium"
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:text="16:16" />
|
tools:text="16:16" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_repeat"
|
android:id="@+id/playback_repeat"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -125,16 +125,18 @@
|
||||||
android:contentDescription="@string/desc_change_repeat"
|
android:contentDescription="@string/desc_change_repeat"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/desc_skip_prev"
|
android:contentDescription="@string/desc_skip_prev"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
||||||
|
@ -153,24 +155,26 @@
|
||||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||||
tools:src="@drawable/ic_play" />
|
tools:src="@drawable/ic_play" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/desc_skip_next"
|
android:contentDescription="@string/desc_skip_next"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_shuffle"
|
android:id="@+id/playback_shuffle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
android:contentDescription="@string/desc_shuffle"
|
android:contentDescription="@string/desc_shuffle"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/spacing_medium">
|
android:padding="@dimen/spacing_medium">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/detail_cover"
|
android:id="@+id/detail_cover"
|
||||||
style="@style/Widget.Auxio.Image.Large"
|
style="@style/Widget.Auxio.Image.Large"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
app:title="@string/lbl_playback"
|
app:title="@string/lbl_playback"
|
||||||
tools:subtitle="@string/lbl_all_songs" />
|
tools:subtitle="@string/lbl_all_songs" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
android:layout_margin="@dimen/spacing_mid_large"
|
android:layout_margin="@dimen/spacing_mid_large"
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:text="16:16" />
|
tools:text="16:16" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_repeat"
|
android:id="@+id/playback_repeat"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -123,18 +123,20 @@
|
||||||
android:contentDescription="@string/desc_change_repeat"
|
android:contentDescription="@string/desc_change_repeat"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/spacing_large"
|
android:layout_marginEnd="@dimen/spacing_large"
|
||||||
android:contentDescription="@string/desc_skip_prev"
|
android:contentDescription="@string/desc_skip_prev"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
@ -152,18 +154,19 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:src="@drawable/ic_pause" />
|
tools:src="@drawable/ic_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/spacing_large"
|
android:layout_marginStart="@dimen/spacing_large"
|
||||||
android:contentDescription="@string/desc_skip_next"
|
android:contentDescription="@string/desc_skip_next"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_shuffle"
|
android:id="@+id/playback_shuffle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -171,6 +174,7 @@
|
||||||
android:contentDescription="@string/desc_shuffle"
|
android:contentDescription="@string/desc_shuffle"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
app:title="@string/lbl_playback"
|
app:title="@string/lbl_playback"
|
||||||
tools:subtitle="@string/lbl_all_songs" />
|
tools:subtitle="@string/lbl_all_songs" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
android:layout_margin="@dimen/spacing_mid_large"
|
android:layout_margin="@dimen/spacing_mid_large"
|
||||||
|
@ -104,26 +104,28 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:text="16:16" />
|
tools:text="16:16" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_repeat"
|
android:id="@+id/playback_repeat"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||||
android:contentDescription="@string/desc_change_repeat"
|
android:contentDescription="@string/desc_change_repeat"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/spacing_mid_large"
|
android:layout_marginEnd="@dimen/spacing_mid_large"
|
||||||
android:contentDescription="@string/desc_skip_prev"
|
android:contentDescription="@string/desc_skip_prev"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
@ -141,18 +143,19 @@
|
||||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||||
tools:src="@drawable/ic_pause" />
|
tools:src="@drawable/ic_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||||
android:contentDescription="@string/desc_skip_next"
|
android:contentDescription="@string/desc_skip_next"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_shuffle"
|
android:id="@+id/playback_shuffle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -160,6 +163,7 @@
|
||||||
android:contentDescription="@string/desc_shuffle"
|
android:contentDescription="@string/desc_shuffle"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/spacing_medium">
|
android:padding="@dimen/spacing_medium">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/detail_cover"
|
android:id="@+id/detail_cover"
|
||||||
style="@style/Widget.Auxio.Image.MidHuge"
|
style="@style/Widget.Auxio.Image.MidHuge"
|
||||||
app:layout_constraintDimensionRatio="1"
|
app:layout_constraintDimensionRatio="1"
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Medium"
|
style="@style/Widget.Auxio.Image.Medium"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:src="@drawable/ic_album" />
|
tools:icon="@drawable/ic_song" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/playback_song"
|
android:id="@+id/playback_song"
|
||||||
|
@ -44,39 +44,42 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
||||||
tools:text="Artist Name / Album Name" />
|
tools:text="Artist Name / Album Name" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_song"
|
app:layout_constraintStart_toEndOf="@+id/playback_song"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_play_pause"
|
android:id="@+id/playback_play_pause"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/sel_playing_state"
|
android:src="@drawable/sel_playing_state"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
|
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_prev"
|
app:layout_constraintStart_toEndOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/spacing_medium">
|
android:padding="@dimen/spacing_medium">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/detail_cover"
|
android:id="@+id/detail_cover"
|
||||||
style="@style/Widget.Auxio.Image.Huge"
|
style="@style/Widget.Auxio.Image.Huge"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
app:title="@string/lbl_playback"
|
app:title="@string/lbl_playback"
|
||||||
tools:subtitle="@string/lbl_all_songs" />
|
tools:subtitle="@string/lbl_all_songs" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:text="16:16" />
|
tools:text="16:16" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_repeat"
|
android:id="@+id/playback_repeat"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -125,17 +125,19 @@
|
||||||
android:contentDescription="@string/desc_change_repeat"
|
android:contentDescription="@string/desc_change_repeat"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/desc_skip_prev"
|
android:contentDescription="@string/desc_skip_prev"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
||||||
|
@ -155,24 +157,26 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:src="@drawable/ic_pause" />
|
tools:src="@drawable/ic_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/desc_skip_next"
|
android:contentDescription="@string/desc_skip_next"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_shuffle"
|
android:id="@+id/playback_shuffle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
android:contentDescription="@string/desc_shuffle"
|
android:contentDescription="@string/desc_shuffle"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:src="@drawable/ic_album" />
|
tools:icon="@drawable/ic_song" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/playback_song"
|
android:id="@+id/playback_song"
|
||||||
|
@ -42,39 +42,42 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
||||||
tools:text="Artist Name / Album Name" />
|
tools:text="Artist Name / Album Name" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_song"
|
app:layout_constraintStart_toEndOf="@+id/playback_song"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_play_pause"
|
android:id="@+id/playback_play_pause"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/sel_playing_state"
|
android:src="@drawable/sel_playing_state"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
|
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_prev"
|
app:layout_constraintStart_toEndOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
android:paddingTop="@dimen/spacing_medium"
|
android:paddingTop="@dimen/spacing_medium"
|
||||||
android:paddingEnd="@dimen/spacing_medium"
|
android:paddingEnd="@dimen/spacing_medium"
|
||||||
android:paddingBottom="@dimen/spacing_small"
|
android:paddingBottom="@dimen/spacing_small"
|
||||||
app:layoutManager="org.oxycblt.auxio.accent.AccentGridLayoutManager"
|
app:layoutManager=".ui.accent.AccentGridLayoutManager"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/accent_cancel"
|
app:layout_constraintBottom_toTopOf="@+id/accent_cancel"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/accent_header"
|
app:layout_constraintTop_toBottomOf="@+id/accent_header"
|
||||||
tools:itemCount="18"
|
tools:itemCount="18"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
|
@ -43,13 +43,14 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
app:layout_constraintTop_toBottomOf="@+id/playback_song"
|
||||||
tools:text="Artist Name / Album Name" />
|
tools:text="Artist Name / Album Name" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_play_pause"
|
android:id="@+id/playback_play_pause"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_small"
|
android:layout_margin="@dimen/spacing_small"
|
||||||
android:contentDescription="@string/desc_play_pause"
|
android:contentDescription="@string/desc_play_pause"
|
||||||
android:src="@drawable/sel_playing_state"
|
android:src="@drawable/sel_playing_state"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
app:title="@string/lbl_playback"
|
app:title="@string/lbl_playback"
|
||||||
tools:subtitle="@string/lbl_all_songs" />
|
tools:subtitle="@string/lbl_all_songs" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/playback_cover"
|
android:id="@+id/playback_cover"
|
||||||
style="@style/Widget.Auxio.Image.Full"
|
style="@style/Widget.Auxio.Image.Full"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||||
tools:text="16:16" />
|
tools:text="16:16" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_repeat"
|
android:id="@+id/playback_repeat"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -109,16 +109,18 @@
|
||||||
android:contentDescription="@string/desc_change_repeat"
|
android:contentDescription="@string/desc_change_repeat"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_prev"
|
android:id="@+id/playback_skip_prev"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/desc_skip_prev"
|
android:contentDescription="@string/desc_skip_prev"
|
||||||
android:src="@drawable/ic_skip_prev"
|
android:src="@drawable/ic_skip_prev"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
|
||||||
|
@ -137,7 +139,7 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:src="@drawable/ic_play" />
|
tools:src="@drawable/ic_play" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_skip_next"
|
android:id="@+id/playback_skip_next"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -145,12 +147,13 @@
|
||||||
android:minWidth="@dimen/size_btn_small"
|
android:minWidth="@dimen/size_btn_small"
|
||||||
android:minHeight="@dimen/size_btn_small"
|
android:minHeight="@dimen/size_btn_small"
|
||||||
android:src="@drawable/ic_skip_next"
|
android:src="@drawable/ic_skip_next"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
|
||||||
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
|
||||||
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.playback.PlaybackButton
|
<org.oxycblt.auxio.ui.StyledImageButton
|
||||||
android:id="@+id/playback_shuffle"
|
android:id="@+id/playback_shuffle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -159,6 +162,7 @@
|
||||||
android:minWidth="@dimen/size_btn_small"
|
android:minWidth="@dimen/size_btn_small"
|
||||||
android:minHeight="@dimen/size_btn_small"
|
android:minHeight="@dimen/size_btn_small"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
|
app:iconSize="@dimen/size_icon_large"
|
||||||
app:hasIndicator="true"
|
app:hasIndicator="true"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
to be alike to other songs. So, add a pastel-ish background to each track number
|
to be alike to other songs. So, add a pastel-ish background to each track number
|
||||||
view. The way we do this is odd, but it's designed this way-->
|
view. The way we do this is odd, but it's designed this way-->
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/song_track_bg"
|
android:id="@+id/song_track_bg"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:src="@drawable/ic_song"
|
android:src="@drawable/ic_song"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
style="@style/Widget.Auxio.ItemLayout">
|
style="@style/Widget.Auxio.ItemLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/artist_image"
|
android:id="@+id/artist_image"
|
||||||
style="@style/Widget.Auxio.Image.Medium"
|
style="@style/Widget.Auxio.Image.Medium"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/spacing_medium">
|
android:padding="@dimen/spacing_medium">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/detail_cover"
|
android:id="@+id/detail_cover"
|
||||||
style="@style/Widget.Auxio.Image.MidHuge"
|
style="@style/Widget.Auxio.Image.MidHuge"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/disc_item"
|
android:id="@+id/disc_item"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:scaleType="matrix"
|
android:scaleType="matrix"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
style="@style/Widget.Auxio.ItemLayout">
|
style="@style/Widget.Auxio.ItemLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/parent_image"
|
android:id="@+id/parent_image"
|
||||||
style="@style/Widget.Auxio.Image.Medium"
|
style="@style/Widget.Auxio.Image.Medium"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/song_album_cover"
|
android:id="@+id/song_album_cover"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
style="@style/Widget.Auxio.ItemLayout">
|
style="@style/Widget.Auxio.ItemLayout">
|
||||||
|
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.ui.StyledImageView
|
||||||
android:id="@+id/song_album_cover"
|
android:id="@+id/song_album_cover"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
android:layout_alignTop="@id/widget_aspect_ratio"
|
android:layout_alignTop="@id/widget_aspect_ratio"
|
||||||
android:layout_alignEnd="@id/widget_aspect_ratio"
|
android:layout_alignEnd="@id/widget_aspect_ratio"
|
||||||
android:layout_alignBottom="@id/widget_aspect_ratio"
|
android:layout_alignBottom="@id/widget_aspect_ratio"
|
||||||
android:src="@drawable/ic_widget_album"
|
android:src="@drawable/ic_remote_default_cover"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
android:layout_alignTop="@id/widget_aspect_ratio"
|
android:layout_alignTop="@id/widget_aspect_ratio"
|
||||||
android:layout_alignEnd="@id/widget_aspect_ratio"
|
android:layout_alignEnd="@id/widget_aspect_ratio"
|
||||||
android:layout_alignBottom="@id/widget_aspect_ratio"
|
android:layout_alignBottom="@id/widget_aspect_ratio"
|
||||||
android:src="@drawable/ic_widget_album"
|
android:src="@drawable/ic_remote_default_cover"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
android:layout_alignTop="@id/widget_aspect_ratio"
|
android:layout_alignTop="@id/widget_aspect_ratio"
|
||||||
android:layout_alignEnd="@id/widget_aspect_ratio"
|
android:layout_alignEnd="@id/widget_aspect_ratio"
|
||||||
android:layout_alignBottom="@id/widget_aspect_ratio"
|
android:layout_alignBottom="@id/widget_aspect_ratio"
|
||||||
android:src="@drawable/ic_widget_album"
|
android:src="@drawable/ic_remote_default_cover"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
android:layout_marginEnd="@dimen/spacing_medium"
|
android:layout_marginEnd="@dimen/spacing_medium"
|
||||||
android:contentDescription="@string/desc_no_cover"
|
android:contentDescription="@string/desc_no_cover"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/ic_widget_album" />
|
android:src="@drawable/ic_remote_default_cover" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
android:layout_alignTop="@id/widget_aspect_ratio"
|
android:layout_alignTop="@id/widget_aspect_ratio"
|
||||||
android:layout_alignEnd="@id/widget_aspect_ratio"
|
android:layout_alignEnd="@id/widget_aspect_ratio"
|
||||||
android:layout_alignBottom="@id/widget_aspect_ratio"
|
android:layout_alignBottom="@id/widget_aspect_ratio"
|
||||||
android:src="@drawable/ic_widget_album"
|
android:src="@drawable/ic_remote_default_cover"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<attr name="cornerRadius" format="dimension" />
|
<attr name="cornerRadius" format="dimension" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="PlaybackButton">
|
<declare-styleable name="StyledImageButton">
|
||||||
|
<attr name="iconSize" format="dimension" />
|
||||||
<attr name="hasIndicator" format="boolean" />
|
<attr name="hasIndicator" format="boolean" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
<dimen name="size_corners_small">8dp</dimen>
|
<dimen name="size_corners_small">8dp</dimen>
|
||||||
<dimen name="size_corners_large">16dp</dimen>
|
<dimen name="size_corners_large">16dp</dimen>
|
||||||
|
|
||||||
<dimen name="size_playback_icon">32dp</dimen>
|
<dimen name="size_icon_normal">24dp</dimen>
|
||||||
|
<dimen name="size_icon_large">32dp</dimen>
|
||||||
|
|
||||||
<dimen name="text_size_ext_label_larger">16sp</dimen>
|
<dimen name="text_size_ext_label_larger">16sp</dimen>
|
||||||
<dimen name="text_size_ext_title_mid_large">18sp</dimen>
|
<dimen name="text_size_ext_title_mid_large">18sp</dimen>
|
||||||
|
|
|
@ -174,7 +174,7 @@
|
||||||
-->
|
-->
|
||||||
<item name="fabSize">normal</item>
|
<item name="fabSize">normal</item>
|
||||||
<item name="fabCustomSize">@dimen/size_btn_large</item>
|
<item name="fabCustomSize">@dimen/size_btn_large</item>
|
||||||
<item name="maxImageSize">@dimen/size_playback_icon</item>
|
<item name="maxImageSize">@dimen/size_icon_large</item>
|
||||||
<item name="android:elevation">0dp</item>
|
<item name="android:elevation">0dp</item>
|
||||||
<item name="elevation">0dp</item>
|
<item name="elevation">0dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue