diff --git a/CHANGELOG.md b/CHANGELOG.md index 4289388ff..b9e7d6ecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### What's New - Folders on external drives can now be excluded on Android Q+ [#134] - Playback bar now has a skip action +- When playing, the cover now shows an animated indicator #### What's Improved - The toolbar in the home UI now collapses when scrolling diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 69c5b40fc..ddbaf79ec 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -209,7 +209,6 @@ class AlbumDetailFragment : DetailFragment(), AlbumDetailAdapter.Listener { } if (parent is Album && parent.id == unlikelyToBeNull(detailModel.currentAlbum.value).id) { - logD("update $song") detailAdapter.highlightSong(song) } else { // Clear the ViewHolders if the mode isn't ALL_SONGS diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt index ed4c2318c..215fb631a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt @@ -31,7 +31,6 @@ import org.oxycblt.auxio.ui.BindingViewHolder import org.oxycblt.auxio.ui.Item import org.oxycblt.auxio.ui.MenuItemListener import org.oxycblt.auxio.ui.SimpleItemCallback -import org.oxycblt.auxio.ui.StyledImageView import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.getPluralSafe @@ -194,21 +193,12 @@ private class AlbumSongViewHolder private constructor(private val binding: ItemA isInvisible = false contentDescription = context.getString(R.string.desc_track_number, item.track) } - - binding.songTrackBg.setImageDrawable(null) } else { binding.songTrack.apply { textSafe = "" isInvisible = true contentDescription = context.getString(R.string.def_track) } - - // Normally we would not re-load the drawable each time and instead - // change the alpha value, but Lollipop gets in our way yet again - // and does some stupid insanity with the alpha value that results - // in such branching. - binding.songTrackBg.setImageDrawable( - StyledImageView.StyledDrawable(binding.context, R.drawable.ic_song)) } binding.songName.textSafe = item.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/ui/StyledImageView.kt b/app/src/main/java/org/oxycblt/auxio/image/BaseStyledImageView.kt similarity index 53% rename from app/src/main/java/org/oxycblt/auxio/ui/StyledImageView.kt rename to app/src/main/java/org/oxycblt/auxio/image/BaseStyledImageView.kt index 8ac6a7094..f5d64307f 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/StyledImageView.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/BaseStyledImageView.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.ui +package org.oxycblt.auxio.image import android.content.Context import android.graphics.Canvas @@ -25,111 +25,67 @@ 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 androidx.core.graphics.drawable.DrawableCompat import coil.dispose -import coil.drawable.CrossfadeDrawable 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. + * The base class for Auxio's images. Do not use this class outside of this module. + * + * Default behavior includes the addition of a tonal background and automatic icon sizing. Other + * behavior is implemented by [StyledImageView] and [ImageGroup]. * - * 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 - * - * TODO: I'll need to make it a whole ViewGroup eventually */ -class StyledImageView +open class BaseStyledImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : AppCompatImageView(context, attrs, defStyleAttr) { - private var cornerRadius = 0f - private var indicator = StyledDrawable(context, R.drawable.ic_equalizer) + private var staticIcon = 0 init { val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageView) - cornerRadius = styledAttrs.getDimension(R.styleable.StyledImageView_cornerRadius, 0f) + staticIcon = styledAttrs.getResourceId(R.styleable.StyledImageView_staticIcon, -1) styledAttrs.recycle() - // 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. As a side-note, this also allows us to re-use the same - // background for both the tonal background color and the corner rounding. - 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(StyledDrawable(context, drawable)) - } - } - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - - if (!isInEditMode) { - val settingsManager = SettingsManager.getInstance() - if (settingsManager.roundCovers) { - (background as MaterialShapeDrawable).setCornerSize(cornerRadius) - } - } - } - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - if (isActivated) { - // We can't modify the view alpha since that would change the background opacity, - // but we also can't modify the image alpha since that breaks CrossfadeDrawable. - // Instead, we just draw the background again when activated in order to obscure - // the actual image, and then draw the indicator. The only other option is to make - // a proper ViewGroup, and I really don't want that. - val src = drawable?.let { if (it is CrossfadeDrawable) it.end else it } - background.alpha = if (src is StyledDrawable) 255 else 128 - background.draw(canvas) - background.alpha = 255 - indicator.draw(canvas) - } } /** Bind the album cover for a [song]. */ - fun bind(song: Song) = loadImpl(song, R.drawable.ic_song, R.string.desc_album_cover) + open fun bind(song: Song) = loadImpl(song, R.drawable.ic_song) /** Bind the album cover for an [album]. */ - fun bind(album: Album) = loadImpl(album, R.drawable.ic_album, R.string.desc_album_cover) + open fun bind(album: Album) = loadImpl(album, R.drawable.ic_album) /** Bind the image for an [artist] */ - fun bind(artist: Artist) = loadImpl(artist, R.drawable.ic_artist, R.string.desc_artist_image) + open fun bind(artist: Artist) = loadImpl(artist, R.drawable.ic_artist) /** Bind the image for a [genre] */ - fun bind(genre: Genre) = loadImpl(genre, R.drawable.ic_genre, R.string.desc_genre_image) + open fun bind(genre: Genre) = loadImpl(genre, R.drawable.ic_genre) + + private fun loadImpl(music: T, @DrawableRes error: Int) { + if (staticIcon > -1) { + throw IllegalStateException("Static StyledImageViews cannot bind new images") + } - private fun loadImpl(music: T, @DrawableRes error: Int, @StringRes desc: Int) { dispose() load(music) { error(StyledDrawable(context, error)) transformations(SquareFrameTransform.INSTANCE) } - contentDescription = context.getString(desc, music.resolveName(context)) } /** diff --git a/app/src/main/java/org/oxycblt/auxio/image/ImageGroup.kt b/app/src/main/java/org/oxycblt/auxio/image/ImageGroup.kt new file mode 100644 index 000000000..67dd80cc1 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/image/ImageGroup.kt @@ -0,0 +1,156 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.image + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import androidx.annotation.AttrRes +import com.google.android.material.shape.MaterialShapeDrawable +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.Song +import org.oxycblt.auxio.settings.SettingsManager +import org.oxycblt.auxio.util.getColorStateListSafe + +/** + * Effectively a super-charged [StyledImageView]. + * + * This class enables the following features alongside the base features pf [StyledImageView]: + * - Activation indicator with an animated icon + * - (Eventually) selection indicator + * - Support for ONE custom view + * + * This class is primarily intended for list items. For most uses, the simpler [StyledImageView] is + * more efficient and suitable. + * + * @author OxygenCobalt + */ +class ImageGroup +@JvmOverloads +constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : + FrameLayout(context, attrs, defStyleAttr) { + private val cornerRadius: Float + + private val inner = BaseStyledImageView(context, attrs) + private var customView: View? = null + private val indicator = ImageGroupIndicator(context) + + init { + // Android wants you to make separate attributes for each view type, but will + // then throw an error if you do because of duplicate attribute names. + @SuppressLint("CustomViewStyleable") + val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageView) + cornerRadius = styledAttrs.getDimension(R.styleable.StyledImageView_cornerRadius, 0f) + styledAttrs.recycle() + + addView(inner) + + // 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. As a side-note, this also allows us to re-use the same + // background for both the tonal background color and the corner rounding. + background = MaterialShapeDrawable() + clipToOutline = true + + if (!isInEditMode) { + val settingsManager = SettingsManager.getInstance() + if (settingsManager.roundCovers) { + (background as MaterialShapeDrawable).setCornerSize(cornerRadius) + } + } + } + + override fun onFinishInflate() { + super.onFinishInflate() + + if (childCount > 2) { + error("Only one custom view is allowed") + } + + customView = + getChildAt(1)?.apply { + background = + MaterialShapeDrawable().apply { + fillColor = context.getColorStateListSafe(R.color.sel_cover_bg) + } + } + + addView(indicator) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + + if (!isInEditMode) { + val settingsManager = SettingsManager.getInstance() + if (settingsManager.roundCovers) { + (background as MaterialShapeDrawable).setCornerSize(cornerRadius) + } + } + + invalidateIndicator() + } + + override fun setActivated(activated: Boolean) { + super.setActivated(activated) + invalidateIndicator() + } + + private fun invalidateIndicator() { + if (isActivated) { + indicator.alpha = 1f + customView?.alpha = 0f + inner.alpha = 0f + } else { + indicator.alpha = 0f + customView?.alpha = 1f + inner.alpha = 1f + } + } + + fun bind(song: Song) { + inner.bind(song) + contentDescription = + context.getString(R.string.desc_album_cover, song.album.resolveName(context)) + } + + fun bind(album: Album) { + inner.bind(album) + contentDescription = + context.getString(R.string.desc_album_cover, album.resolveName(context)) + } + + fun bind(artist: Artist) { + inner.bind(artist) + contentDescription = + context.getString(R.string.desc_artist_image, artist.resolveName(context)) + } + + fun bind(genre: Genre) { + inner.bind(genre) + contentDescription = + context.getString(R.string.desc_genre_image, genre.resolveName(context)) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/image/ImageGroupIndicator.kt b/app/src/main/java/org/oxycblt/auxio/image/ImageGroupIndicator.kt new file mode 100644 index 000000000..e8725b3b9 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/image/ImageGroupIndicator.kt @@ -0,0 +1,101 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.image + +import android.content.Context +import android.graphics.Matrix +import android.graphics.RectF +import android.graphics.drawable.AnimationDrawable +import android.util.AttributeSet +import androidx.annotation.AttrRes +import androidx.appcompat.widget.AppCompatImageView +import com.google.android.material.shape.MaterialShapeDrawable +import org.oxycblt.auxio.R +import org.oxycblt.auxio.util.getColorStateListSafe + +/** + * Represents the animated indicator that is shown when [ImageGroup] is active. + * + * AnimationDrawable, the drawable that this view is backed by, is really finicky. Basically, it has + * to be set as the drawable of an ImageView to work correctly, and will just not draw anywhere + * else. As a result, we have to create a custom view that emulates [StyledImageView] and + * [StyledDrawable] simultaneously while also managing the animation state. + * + * @author OxygenCobalt + */ +class ImageGroupIndicator +@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() + + init { + scaleType = ScaleType.MATRIX + setImageResource(R.drawable.ic_animated_equalizer) + imageTintList = context.getColorStateListSafe(R.color.sel_on_cover_bg) + background = + MaterialShapeDrawable().apply { + fillColor = context.getColorStateListSafe(R.color.sel_cover_bg) + } + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + + // Instead of using StyledDrawable (which would break the animation), we scale + // up the animated icon using a matrix. This is okay, as it won't fall victim to + // the same issues that come with using a matrix in StyledImageView + 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. + + val iconWidth = measuredWidth / 2f + val iconHeight = measuredHeight / 2f + + // First scale the icon up to the desired size. + matrixSrc.set( + 0f, + 0f, + drawable.intrinsicWidth.toFloat(), + drawable.intrinsicHeight.toFloat()) + matrixDst.set(0f, 0f, iconWidth, iconHeight) + 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 - iconWidth) / 2f, (measuredHeight - iconHeight) / 2f) + } + } + } + + override fun setActivated(activated: Boolean) { + super.setActivated(activated) + val icon = drawable as AnimationDrawable + if (activated) { + icon.start() + } else { + icon.stop() + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/image/StyledDrawable.kt b/app/src/main/java/org/oxycblt/auxio/image/StyledDrawable.kt new file mode 100644 index 000000000..96ea2e0df --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/image/StyledDrawable.kt @@ -0,0 +1,66 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.image + +import android.content.Context +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.PixelFormat +import android.graphics.drawable.Drawable +import androidx.core.graphics.drawable.DrawableCompat +import org.oxycblt.auxio.R +import org.oxycblt.auxio.util.getColorStateListSafe + +/** + * The internal drawable used by Auxio's images. Do not use this outside of this module. + * + * This enables a few features: + * - Automatic tinting to the correct image tint + * - Automatic sizing to HALF of the canvas. + * + * @author OxygenCobalt + */ +class StyledDrawable(context: Context, private val src: Drawable) : Drawable() { + init { + // Re-tint the drawable to something that will play along with the background. + // Done here because this call (and nothing else) miraculously works on Lollipop devices + DrawableCompat.setTintList(src, context.getColorStateListSafe(R.color.sel_on_cover_bg)) + } + + 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 +} diff --git a/app/src/main/java/org/oxycblt/auxio/image/StyledImageView.kt b/app/src/main/java/org/oxycblt/auxio/image/StyledImageView.kt new file mode 100644 index 000000000..87dde24b3 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/image/StyledImageView.kt @@ -0,0 +1,91 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.image + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.AttrRes +import androidx.appcompat.widget.AppCompatImageView +import com.google.android.material.shape.MaterialShapeDrawable +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.Song +import org.oxycblt.auxio.settings.SettingsManager + +/** + * 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) : + BaseStyledImageView(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() + + // 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. As a side-note, this also allows us to re-use the same + // background for both the tonal background color and the corner rounding. + clipToOutline = true + + if (!isInEditMode) { + val settingsManager = SettingsManager.getInstance() + if (settingsManager.roundCovers) { + (background as MaterialShapeDrawable).setCornerSize(cornerRadius) + } + } + } + + override fun bind(song: Song) { + super.bind(song) + contentDescription = + context.getString(R.string.desc_album_cover, song.album.resolveName(context)) + } + + override fun bind(album: Album) { + super.bind(album) + contentDescription = + context.getString(R.string.desc_album_cover, album.resolveName(context)) + } + + override fun bind(artist: Artist) { + super.bind(artist) + contentDescription = + context.getString(R.string.desc_artist_image, artist.resolveName(context)) + } + + override fun bind(genre: Genre) { + super.bind(genre) + contentDescription = + context.getString(R.string.desc_genre_image, genre.resolveName(context)) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt b/app/src/main/java/org/oxycblt/auxio/playback/IndicatorMaterialButton.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt rename to app/src/main/java/org/oxycblt/auxio/playback/IndicatorMaterialButton.kt index 7183286b3..7cfdc50a2 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/IndicatorMaterialButton.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.ui +package org.oxycblt.auxio.playback import android.content.Context import android.graphics.Canvas diff --git a/app/src/main/res/color/sel_track_cover.xml b/app/src/main/res/color/sel_track_cover.xml deleted file mode 100644 index d7ade8a18..000000000 --- a/app/src/main/res/color/sel_track_cover.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_animated_equalizer.xml b/app/src/main/res/drawable/ic_animated_equalizer.xml new file mode 100644 index 000000000..9b81fe2db --- /dev/null +++ b/app/src/main/res/drawable/ic_animated_equalizer.xml @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_equalizer.xml b/app/src/main/res/drawable/ic_equalizer.xml deleted file mode 100644 index c1aa427a0..000000000 --- a/app/src/main/res/drawable/ic_equalizer.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/app/src/main/res/layout-h600dp/item_detail.xml b/app/src/main/res/layout-h600dp/item_detail.xml index 25a2bffda..3e942fbfd 100644 --- a/app/src/main/res/layout-h600dp/item_detail.xml +++ b/app/src/main/res/layout-h600dp/item_detail.xml @@ -6,14 +6,14 @@ android:layout_height="match_parent" android:padding="@dimen/spacing_medium"> - + tools:staticIcon="@drawable/ic_artist" /> - - - - + tools:staticIcon="@drawable/ic_artist" /> - - - - - - - + tools:staticIcon="@drawable/ic_artist" /> - - + tools:staticIcon="@drawable/ic_artist" /> - - - - - + tools:placeholderIcon="@drawable/ic_song" /> - - - - - + app:staticIcon="@drawable/ic_song" + tools:visibility="invisible"> + + + + + @@ -59,9 +61,9 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:textColor="?android:attr/textColorSecondary" - app:layout_constraintBottom_toBottomOf="@+id/song_track" + app:layout_constraintBottom_toBottomOf="@+id/song_track_bg" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/song_track" + app:layout_constraintStart_toEndOf="@+id/song_track_bg" app:layout_constraintTop_toBottomOf="@+id/song_name" tools:text="16:16" /> diff --git a/app/src/main/res/layout/item_artist.xml b/app/src/main/res/layout/item_artist.xml index 3c321027d..19483e1f8 100644 --- a/app/src/main/res/layout/item_artist.xml +++ b/app/src/main/res/layout/item_artist.xml @@ -4,13 +4,13 @@ xmlns:tools="http://schemas.android.com/tools" style="@style/Widget.Auxio.ItemLayout"> - + tools:staticIcon="@drawable/ic_artist" /> - + tools:staticIcon="@drawable/ic_artist" /> - - + tools:staticIcon="@drawable/ic_artist" /> - + tools:staticIcon="@drawable/ic_album" /> - + tools:staticIcon="@drawable/ic_album" /> - - \ - \ - \ - \ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 670a35a76..33611e92d 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -2,6 +2,7 @@ +