ui: add image playing indicator

Add a playing indicator to cover art.

This is simply to improve the general aestethics of this view. Of
course, the current way I implement this is incredibly stupid and I
plan to replace it.
This commit is contained in:
OxygenCobalt 2022-06-10 09:47:37 -06:00
parent 1d66907862
commit ffe7298665
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 51 additions and 16 deletions

View file

@ -10,6 +10,8 @@
- The toolbar in the home UI now collapses when scrolling
- The toolbar layout is now consistent with Material Design 3
- Genre parsing now handles multiple integer values and cover/remix indicators (May wipe playback state)
#### What's Fixed
- Playback bar now picks the larger inset in case that gesture inset is missing [#149]
#### Dev/Meta

View file

@ -74,8 +74,7 @@ abstract class BaseFetcher : Fetcher {
fetchMediaStoreCovers(context, album)
}
} catch (e: Exception) {
logW("Unable to extract album art due to an error")
logW(e.stackTraceToString())
logW("Unable to extract album art due to an error: $e")
null
}
}

View file

@ -54,7 +54,7 @@ constructor(
FrameLayout(context, attrs, defStyleAttr),
Slider.OnSliderTouchListener,
Slider.OnChangeListener {
private val binding = ViewSeekBarBinding.inflate(context.inflater, this, true)
private val binding = ViewSeekBarBinding.inflate(context.inflater, this)
init {
binding.seekBarSlider.addOnSliderTouchListener(this)

View file

@ -29,6 +29,7 @@ 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
@ -50,19 +51,18 @@ import org.oxycblt.auxio.util.getDrawableSafe
* of the view size, and corner radius application depending on user preference.
* @author OxygenCobalt
*
* TODO: Rework this layout into a total ViewGroup that enables more customization + an indicator
* TODO: I'll need to make it a whole ViewGroup eventually
*/
class StyledImageView
@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)
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
@ -95,19 +95,35 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
}
}
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) = load(song, R.drawable.ic_song, R.string.desc_album_cover)
fun bind(song: Song) = loadImpl(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)
fun bind(album: Album) = loadImpl(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)
fun bind(artist: Artist) = loadImpl(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)
fun bind(genre: Genre) = loadImpl(genre, R.drawable.ic_genre, R.string.desc_genre_image)
private fun <T : Music> load(music: T, @DrawableRes error: Int, @StringRes desc: Int) {
private fun <T : Music> loadImpl(music: T, @DrawableRes error: Int, @StringRes desc: Int) {
dispose()
load(music) {
error(StyledDrawable(context, error))

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/transparent" android:state_activated="true" />
<item android:color="?attr/colorSurfaceInverse" />
</selector>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M10,20h4L14,4h-4v16zM4,20h4v-8L4,12v8zM16,9v11h4L20,9h-4z"/>
</vector>

View file

@ -8,7 +8,8 @@
<!--
We don't want to show an album cover, but we still want the spacing of this song
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.ui.StyledImageView
android:id="@+id/song_track_bg"
@ -27,7 +28,7 @@
android:maxLines="1"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
android:textColor="@color/sel_on_cover_bg"
android:textColor="@color/sel_track_cover"
app:autoSizeMaxTextSize="@dimen/text_size_track_number_max"
app:autoSizeMinTextSize="@dimen/text_size_track_number_min"
app:autoSizeStepGranularity="@dimen/text_size_track_number_step"

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">
<com.google.android.material.slider.Slider
android:id="@+id/seek_bar_slider"
@ -41,4 +42,4 @@
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
tools:text="16:16" />
</FrameLayout>
</merge>