coil: make rounded images more nuanced
Create a custom view for rounded images, making them more nuanced in the process. The previous method for applying rounded images in-app was generally clunky and fragile. Introduce a new custom view that actually takes a cornerRadius attribute from the ImageView itself that then applies it whenever the user enables the setting. This also allows rounded images to be more nuanced, as typical 8dp elevation can be used for small views and a more fitting 16dp radius can be used for large views.
This commit is contained in:
parent
280b582efa
commit
61dbfe3185
31 changed files with 83 additions and 53 deletions
|
@ -3,6 +3,7 @@
|
|||
## dev [v2.2.2 or 2.3.0]
|
||||
|
||||
#### What's Improved
|
||||
- Rounded images are more nuanced
|
||||
- Shuffle and Repeat mode buttons now have more contrast when they are turned on
|
||||
|
||||
#### What's Changed
|
||||
|
|
|
@ -79,10 +79,6 @@ class MainFragment : Fragment() {
|
|||
// but for some insane reason google decided to cripple the window APIs one could use
|
||||
// to limit it's size. So, we just have our own special layout that is shown whenever
|
||||
// the screen is too small because of course we have to.
|
||||
// Another fun fact: smallestScreenWidthDp is completely bugged and uses the total
|
||||
// screen size, even when the window is smaller. This basically borks split screen
|
||||
// even more than it already does. Fun!
|
||||
|
||||
if (requireActivity().isInMultiWindowMode) {
|
||||
val config = resources.configuration
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ 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
|
||||
|
||||
// --- BINDING ADAPTERS ---
|
||||
|
||||
|
@ -66,21 +65,6 @@ fun ImageView.bindGenreImage(genre: Genre?) = load(genre, R.drawable.ic_genre)
|
|||
fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int) {
|
||||
dispose()
|
||||
|
||||
// We don't round album covers by default as it desecrates album artwork, but we do provide
|
||||
// an option if one wants it.
|
||||
// As for why we use clipToOutline instead of coils RoundedCornersTransformation, the radii
|
||||
// of an image's corners is dependent on the actual dimensions of the image, which would force
|
||||
// us to resize all images to a fixed size. clipToOutline is pretty much always cheaper as long
|
||||
// as we have a perfectly-square image.
|
||||
val settingsManager = SettingsManager.getInstance()
|
||||
if (settingsManager.roundCovers && background == null) {
|
||||
setBackgroundResource(R.drawable.ui_rounded_cutout)
|
||||
clipToOutline = true
|
||||
} else if (!settingsManager.roundCovers && background != null) {
|
||||
background = null
|
||||
clipToOutline = false
|
||||
}
|
||||
|
||||
load(music) {
|
||||
error(error)
|
||||
transformations(SquareFrameTransform())
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.oxycblt.auxio.coil
|
||||
|
||||
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.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.getColorSafe
|
||||
import org.oxycblt.auxio.util.stateList
|
||||
|
||||
class RoundableImageView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@AttrRes defStyleAttr: Int = 0
|
||||
) : AppCompatImageView(context, attrs, defStyleAttr) {
|
||||
init {
|
||||
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.RoundableImageView)
|
||||
val cornerRadius = styledAttrs.getDimension(R.styleable.RoundableImageView_cornerRadius, 0.0f)
|
||||
styledAttrs.recycle()
|
||||
|
||||
background = MaterialShapeDrawable().apply {
|
||||
setCornerSize(cornerRadius)
|
||||
fillColor = context.getColorSafe(android.R.color.transparent).stateList
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
|
||||
// We don't round album covers by default as it desecrates album artwork, but we do
|
||||
// provide an option if one wants it.
|
||||
// As for why we use clipToOutline instead of coils RoundedCornersTransformation, the radii
|
||||
// of an image's corners is dependent on the actual dimensions of the image, which would
|
||||
// force us to resize all images to a fixed size. clipToOutline is pretty much always
|
||||
// cheaper as long as we have a perfectly-square image.
|
||||
val settingsManager = SettingsManager.getInstance()
|
||||
clipToOutline = settingsManager.roundCovers
|
||||
}
|
||||
}
|
|
@ -159,7 +159,9 @@ class HomeFragment : Fragment() {
|
|||
).attach()
|
||||
}
|
||||
|
||||
binding.homeShuffleFab.setup(playbackModel)
|
||||
binding.homeFab.setOnClickListener {
|
||||
playbackModel.shuffleAll()
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
|
@ -169,12 +171,12 @@ class HomeFragment : Fragment() {
|
|||
musicModel.loaderResponse.observe(viewLifecycleOwner) { response ->
|
||||
// Handle the loader response.
|
||||
when (response) {
|
||||
is MusicStore.Response.Ok -> binding.homeShuffleFab.show()
|
||||
is MusicStore.Response.Ok -> binding.homeFab.show()
|
||||
|
||||
// While loading or during an error, make sure we keep the shuffle fab hidden so
|
||||
// that any kind of playback is impossible. PlaybackStateManager also relies on this
|
||||
// invariant, so please don't change it.
|
||||
else -> binding.homeShuffleFab.hide()
|
||||
else -> binding.homeFab.hide()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,9 +188,9 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
|
||||
if (scrolling) {
|
||||
binding.homeShuffleFab.hide()
|
||||
binding.homeFab.hide()
|
||||
} else {
|
||||
binding.homeShuffleFab.show()
|
||||
binding.homeFab.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="@dimen/spacing_small" />
|
||||
</shape>
|
|
@ -10,7 +10,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/detail_cover"
|
||||
style="@style/Widget.Auxio.Image.Huge"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
tools:subtitle="@string/lbl_all_songs"
|
||||
app:title="@string/lbl_playback" />
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/detail_cover"
|
||||
style="@style/Widget.Auxio.Image.Large"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:menu="@menu/menu_playback" />
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
tools:subtitle="@string/lbl_all_songs"
|
||||
app:menu="@menu/menu_playback" />
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_large"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/detail_cover"
|
||||
style="@style/Widget.Auxio.Image.MidHuge"
|
||||
app:layout_constraintDimensionRatio="1"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/detail_cover"
|
||||
style="@style/Widget.Auxio.Image.Huge"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
tools:subtitle="@string/lbl_all_songs"
|
||||
app:menu="@menu/menu_playback" />
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
tools:subtitle="@string/lbl_all_songs"
|
||||
app:menu="@menu/menu_playback" />
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_mid_large"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(album.name)}"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/song_track_placeholder"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/artist_image"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_artist_image(artist.resolvedName)}"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(album.name)}"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.name)}"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/detail_cover"
|
||||
style="@style/Widget.Auxio.Image.MidHuge"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/genre_image"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_genre_image(genre.resolvedName)}"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.name)}"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.name)}"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<ImageView
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_small"
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="RoundableImageView">
|
||||
<attr name="cornerRadius" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="PlaybackButton">
|
||||
<attr name="hasIndicator" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Spacing Namespace | Dimens for padding/margin attributes -->
|
||||
<dimen name="spacing_tiny">4dp</dimen>
|
||||
<dimen name="spacing_small">8dp</dimen>
|
||||
<dimen name="spacing_medium">16dp</dimen>
|
||||
<dimen name="spacing_mid_large">24dp</dimen>
|
||||
|
@ -17,6 +16,9 @@
|
|||
<dimen name="size_cover_mid_huge">192dp</dimen>
|
||||
<dimen name="size_cover_huge">256dp</dimen>
|
||||
|
||||
<dimen name="size_corners_small">8dp</dimen>
|
||||
<dimen name="size_corners_large">16dp</dimen>
|
||||
|
||||
<dimen name="size_track_number">32dp</dimen>
|
||||
<dimen name="size_playback_icon">32dp</dimen>
|
||||
|
||||
|
|
|
@ -26,32 +26,38 @@
|
|||
<style name="Widget.Auxio.Image.Small" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_compact</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_compact</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_small</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.Medium" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_normal</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_normal</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_small</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.Large" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_large</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_large</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_large</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.MidHuge" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_mid_huge</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_mid_huge</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_large</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.Huge" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_huge</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_huge</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_large</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.Full" parent="">
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">0dp</item>
|
||||
<item name="layout_constraintDimensionRatio">1</item>
|
||||
<item name="cornerRadius">@dimen/size_corners_large</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.ItemLayout" parent="">
|
||||
|
|
Loading…
Reference in a new issue