Standardize coil usage

Completely switch over to use ImageRequest.Builder instead of the load extension function, spin off the Artist Image fetcher & Image BindingAdapters to a seperate module.
This commit is contained in:
OxygenCobalt 2020-09-07 10:52:07 -06:00
parent a93c0f4af3
commit e9ee9d1ef1
10 changed files with 117 additions and 89 deletions

View file

@ -68,7 +68,7 @@ dependencies {
// --- THIRD PARTY --- // --- THIRD PARTY ---
// Image loading // Image loading
implementation 'io.coil-kt:coil:0.12.0' implementation 'io.coil-kt:coil:0.13.0'
// Material // Material
implementation 'com.google.android.material:material:1.3.0-alpha02' implementation 'com.google.android.material:material:1.3.0-alpha02'

View file

@ -11,12 +11,14 @@ import org.oxycblt.auxio.theme.accent
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
// TODO: Collapse LoadingFragment/MainFragment into MainActivity. // Debug placeholder so I can test dark and light modes. Ignore.
override fun onAttachedToWindow() {
super.onAttachedToWindow()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
// Debugging placeholder
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
// Apply the theme // Apply the theme
setTheme(accent.second) setTheme(accent.second)

View file

@ -27,21 +27,9 @@ class MainFragment : Fragment() {
private val libraryFragment: LibraryFragment by lazy { LibraryFragment() } private val libraryFragment: LibraryFragment by lazy { LibraryFragment() }
private val songsFragment: SongsFragment by lazy { SongsFragment() } private val songsFragment: SongsFragment by lazy { SongsFragment() }
private val colorSelected: Int by lazy {
accent.first.toColor(requireContext())
}
private val colorDeselected: Int by lazy {
getTransparentAccent(
requireContext(),
accent.first,
getInactiveAlpha(accent.first)
)
}
private val tabIcons = listOf( private val tabIcons = listOf(
R.drawable.ic_library, R.drawable.ic_library,
R.drawable.ic_music R.drawable.ic_song
) )
override fun onCreateView( override fun onCreateView(
@ -56,13 +44,20 @@ class MainFragment : Fragment() {
val adapter = PagerAdapter(requireActivity()) val adapter = PagerAdapter(requireActivity())
binding.viewPager.adapter = adapter binding.viewPager.adapter = adapter
val colorActive = accent.first.toColor(requireContext())
val colorInactive = getTransparentAccent(
requireContext(),
accent.first,
getInactiveAlpha(accent.first)
)
// Link the ViewPager & Tab View // Link the ViewPager & Tab View
TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position -> TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position ->
tab.icon = ContextCompat.getDrawable(requireContext(), tabIcons[position]) tab.icon = ContextCompat.getDrawable(requireContext(), tabIcons[position])
// Set the icon tint to deselected if its not the default tab // Set the icon tint to deselected if its not the default tab
if (position > 0) { if (position > 0) {
tab.icon?.setTint(colorDeselected) tab.icon?.setTint(colorInactive)
} }
// Init the fragment // Init the fragment
@ -74,11 +69,11 @@ class MainFragment : Fragment() {
object : TabLayout.OnTabSelectedListener { object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) { override fun onTabSelected(tab: TabLayout.Tab) {
tab.icon?.setTint(colorSelected) tab.icon?.setTint(colorActive)
} }
override fun onTabUnselected(tab: TabLayout.Tab) { override fun onTabUnselected(tab: TabLayout.Tab) {
tab.icon?.setTint(colorDeselected) tab.icon?.setTint(colorInactive)
} }
override fun onTabReselected(tab: TabLayout.Tab?) { override fun onTabReselected(tab: TabLayout.Tab?) {

View file

@ -1,4 +1,4 @@
package org.oxycblt.auxio.music.coil package org.oxycblt.auxio.coil
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap

View file

@ -0,0 +1,81 @@
package org.oxycblt.auxio.coil
import android.net.Uri
import android.widget.ImageView
import androidx.databinding.BindingAdapter
import coil.Coil
import coil.request.ImageRequest
import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.models.Album
import org.oxycblt.auxio.music.models.Artist
import org.oxycblt.auxio.music.models.Song
private var artistImageFetcher: ArtistImageFetcher? = null
// Get the cover art for a song or album
@BindingAdapter("coverArt")
fun ImageView.getCoverArt(song: Song) {
val request = ImageRequest.Builder(context)
.data(song.album.coverUri)
.crossfade(true)
.placeholder(android.R.color.transparent)
.error(R.drawable.ic_artist)
.crossfade(true)
.target(this)
.build()
Coil.imageLoader(context).enqueue(request)
}
@BindingAdapter("coverArt")
fun ImageView.getCoverArt(album: Album) {
val request = ImageRequest.Builder(context)
.data(album.coverUri)
.crossfade(true)
.placeholder(android.R.color.transparent)
.error(R.drawable.ic_artist)
.crossfade(true)
.target(this)
.build()
Coil.imageLoader(context).enqueue(request)
}
// Get the artist image
@BindingAdapter("artistImage")
fun ImageView.getArtistImage(artist: Artist) {
val request = if (artist.numAlbums >= 4) {
val uris = mutableListOf<Uri>()
for (i in 0..3) {
uris.add(artist.albums[i].coverUri)
}
// Initialize the fetcher if it hasn't been already.
if (artistImageFetcher == null) {
artistImageFetcher = ArtistImageFetcher(context)
}
// Manually create an image request, as that's the only way to add a fetcher that
// takes a list of uris AFAIK.
ImageRequest.Builder(context)
.data(uris)
.fetcher(artistImageFetcher!!)
.crossfade(true)
.placeholder(android.R.color.transparent)
.error(R.drawable.ic_artist)
.target(this)
.build()
} else {
ImageRequest.Builder(context)
.data(artist.albums[0].coverUri)
.crossfade(true)
.placeholder(android.R.color.transparent)
.error(R.drawable.ic_artist)
.crossfade(true)
.target(this)
.build()
}
Coil.imageLoader(context).enqueue(request)
}

View file

@ -3,17 +3,11 @@ package org.oxycblt.auxio.music
import android.content.ContentUris import android.content.ContentUris
import android.net.Uri import android.net.Uri
import android.provider.MediaStore import android.provider.MediaStore
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.databinding.BindingAdapter import androidx.databinding.BindingAdapter
import coil.Coil
import coil.load
import coil.request.ImageRequest
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.coil.ArtistImageFetcher
import org.oxycblt.auxio.music.models.Album import org.oxycblt.auxio.music.models.Album
import org.oxycblt.auxio.music.models.Artist import org.oxycblt.auxio.music.models.Artist
import org.oxycblt.auxio.music.models.Song
private val ID3_GENRES = arrayOf( private val ID3_GENRES = arrayOf(
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
@ -86,50 +80,3 @@ fun TextView.getArtistCounts(artist: Artist) {
text = context.getString(R.string.format_double_counts, albums, songs) text = context.getString(R.string.format_double_counts, albums, songs)
} }
// Get the cover art
@BindingAdapter("coverArt")
fun ImageView.getCoverArt(song: Song) {
load(song.album.coverUri) {
crossfade(true)
placeholder(android.R.color.transparent)
error(R.drawable.ic_music)
}
}
@BindingAdapter("coverArt")
fun ImageView.getCoverArt(album: Album) {
load(album.coverUri) {
crossfade(true)
placeholder(android.R.color.transparent)
error(R.drawable.ic_album)
}
}
@BindingAdapter("artistImage")
fun ImageView.getArtistImage(artist: Artist) {
if (artist.numAlbums >= 4) {
val uris = mutableListOf<Uri>()
for (i in 0..3) {
uris.add(artist.albums[i].coverUri)
}
val request = ImageRequest.Builder(context)
.data(uris)
.fetcher(ArtistImageFetcher(context))
.crossfade(true)
.placeholder(android.R.color.transparent)
.error(R.drawable.ic_artist)
.target(this)
.build()
Coil.imageLoader(context).enqueue(request)
} else {
load(artist.albums[0].coverUri) {
crossfade(true)
placeholder(android.R.color.transparent)
error(R.drawable.ic_music)
}
}
}

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="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
</vector>

View file

@ -4,12 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"> tools:context=".MainActivity">
<FrameLayout <androidx.fragment.app.FragmentContainerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="@+id/nav_host_fragment" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -17,6 +12,4 @@
app:defaultNavHost="true" app:defaultNavHost="true"
app:navGraph="@navigation/nav_main" app:navGraph="@navigation/nav_main"
tools:ignore="FragmentTagUsage" /> tools:ignore="FragmentTagUsage" />
</FrameLayout>
</layout> </layout>

View file

@ -16,7 +16,6 @@
android:background="?android:attr/windowBackground" android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal" android:elevation="@dimen/elevation_normal"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold" app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/title_all_songs" app:title="@string/title_all_songs"
tools:titleTextColor="@color/blue" /> tools:titleTextColor="@color/blue" />