image: add selection indicator
Add a selection indicator to ImageGroup.
This commit is contained in:
parent
0598409ca5
commit
abd51ad16e
4 changed files with 66 additions and 14 deletions
|
@ -21,7 +21,6 @@ import android.os.Bundle
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
|
|
|
@ -20,16 +20,21 @@ package org.oxycblt.auxio.image
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.ImageView
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.core.view.updateMarginsRelative
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.Genre
|
import org.oxycblt.auxio.music.Genre
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
|
import org.oxycblt.auxio.util.getAttrColorCompat
|
||||||
import org.oxycblt.auxio.util.getColorCompat
|
import org.oxycblt.auxio.util.getColorCompat
|
||||||
|
import org.oxycblt.auxio.util.getDimenSize
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Effectively a super-charged [StyledImageView].
|
* Effectively a super-charged [StyledImageView].
|
||||||
|
@ -51,7 +56,8 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
private val cornerRadius: Float
|
private val cornerRadius: Float
|
||||||
private val inner: StyledImageView
|
private val inner: StyledImageView
|
||||||
private var customView: View? = null
|
private var customView: View? = null
|
||||||
private val indicator: IndicatorView
|
private val playingIndicator: IndicatorView
|
||||||
|
private val selectionIndicator: ImageView
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Android wants you to make separate attributes for each view type, but will
|
// Android wants you to make separate attributes for each view type, but will
|
||||||
|
@ -62,7 +68,14 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
styledAttrs.recycle()
|
styledAttrs.recycle()
|
||||||
|
|
||||||
inner = StyledImageView(context, attrs)
|
inner = StyledImageView(context, attrs)
|
||||||
indicator = IndicatorView(context).apply { cornerRadius = this@ImageGroup.cornerRadius }
|
playingIndicator =
|
||||||
|
IndicatorView(context).apply { cornerRadius = this@ImageGroup.cornerRadius }
|
||||||
|
selectionIndicator =
|
||||||
|
ImageView(context).apply {
|
||||||
|
imageTintList = context.getAttrColorCompat(R.attr.colorOnPrimary)
|
||||||
|
setImageResource(R.drawable.ic_check_20)
|
||||||
|
setBackgroundResource(R.drawable.ui_selection_badge_bg)
|
||||||
|
}
|
||||||
|
|
||||||
addView(inner)
|
addView(inner)
|
||||||
}
|
}
|
||||||
|
@ -83,44 +96,65 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addView(indicator)
|
addView(playingIndicator)
|
||||||
|
addView(
|
||||||
|
selectionIndicator,
|
||||||
|
LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
|
||||||
|
gravity = Gravity.BOTTOM or Gravity.END
|
||||||
|
val spacing = context.getDimenSize(R.dimen.spacing_tiny)
|
||||||
|
updateMarginsRelative(bottom = spacing, end = spacing)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
super.onAttachedToWindow()
|
super.onAttachedToWindow()
|
||||||
invalidateIndicator()
|
invalidateAlpha()
|
||||||
|
invalidatePlayingIndicator()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setActivated(activated: Boolean) {
|
override fun setActivated(activated: Boolean) {
|
||||||
super.setActivated(activated)
|
super.setActivated(activated)
|
||||||
invalidateIndicator()
|
invalidateAlpha()
|
||||||
|
invalidatePlayingIndicator()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setEnabled(enabled: Boolean) {
|
override fun setEnabled(enabled: Boolean) {
|
||||||
super.setEnabled(enabled)
|
super.setEnabled(enabled)
|
||||||
invalidateIndicator()
|
invalidateAlpha()
|
||||||
|
invalidatePlayingIndicator()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setSelected(selected: Boolean) {
|
||||||
|
super.setSelected(selected)
|
||||||
|
invalidateSelectionIndicator()
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPlaying: Boolean
|
var isPlaying: Boolean
|
||||||
get() = indicator.isPlaying
|
get() = playingIndicator.isPlaying
|
||||||
set(value) {
|
set(value) {
|
||||||
indicator.isPlaying = value
|
playingIndicator.isPlaying = value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidateIndicator() {
|
private fun invalidateAlpha() {
|
||||||
|
alpha = if (isActivated || isEnabled) 1f else 0.5f
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invalidatePlayingIndicator() {
|
||||||
if (isActivated) {
|
if (isActivated) {
|
||||||
alpha = 1f
|
|
||||||
customView?.alpha = 0f
|
customView?.alpha = 0f
|
||||||
inner.alpha = 0f
|
inner.alpha = 0f
|
||||||
indicator.alpha = 1f
|
playingIndicator.alpha = 1f
|
||||||
} else {
|
} else {
|
||||||
alpha = if (isEnabled) 1f else 0.5f
|
|
||||||
customView?.alpha = 1f
|
customView?.alpha = 1f
|
||||||
inner.alpha = 1f
|
inner.alpha = 1f
|
||||||
indicator.alpha = 0f
|
playingIndicator.alpha = 0f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun invalidateSelectionIndicator() {
|
||||||
|
selectionIndicator.alpha = if (isSelected) 1f else 0f
|
||||||
|
}
|
||||||
|
|
||||||
fun bind(song: Song) {
|
fun bind(song: Song) {
|
||||||
inner.bind(song)
|
inner.bind(song)
|
||||||
contentDescription =
|
contentDescription =
|
||||||
|
|
10
app/src/main/res/drawable/ic_check_20.xml
Normal file
10
app/src/main/res/drawable/ic_check_20.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="20dp"
|
||||||
|
android:height="20dp"
|
||||||
|
android:viewportWidth="20"
|
||||||
|
android:viewportHeight="20"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M8.229,14.062 L4.708,10.521 5.75,9.479 8.229,11.938 14.25,5.938 15.292,7Z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ui_selection_badge_bg.xml
Normal file
9
app/src/main/res/drawable/ui_selection_badge_bg.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval"
|
||||||
|
android:tint="?attr/colorPrimary">
|
||||||
|
|
||||||
|
<size
|
||||||
|
android:width="20dp"
|
||||||
|
android:height="20dp" />
|
||||||
|
</shape>
|
Loading…
Reference in a new issue