Add RecyclerView to LibraryFragment

Add a basic RecyclerView to LibraryFragment that shows every album.
This commit is contained in:
OxygenCobalt 2020-08-24 14:53:13 -06:00
parent 37b071de0d
commit c04a90c3fa
8 changed files with 126 additions and 20 deletions

View file

@ -7,9 +7,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
import org.oxycblt.auxio.library.recycler.AlbumDataAdapter
import org.oxycblt.auxio.music.MusicRepository
class LibraryFragment : Fragment() {
@ -27,11 +29,16 @@ class LibraryFragment : Fragment() {
inflater, R.layout.fragment_library, container, false
)
libraryModel
val adapter = AlbumDataAdapter()
binding.libraryRecycler.adapter = adapter
val albums = MusicRepository.getInstance().albums.value
binding.testAlbum.setImageBitmap(albums?.get((0..albums.size).random())?.cover)
val repo = MusicRepository.getInstance()
repo.albums.observe(
viewLifecycleOwner,
Observer {
adapter.data = it
}
)
Log.d(this::class.simpleName, "Fragment created.")

View file

@ -0,0 +1,39 @@
package org.oxycblt.auxio.library.recycler
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import org.oxycblt.auxio.databinding.LibraryItemBinding
import org.oxycblt.auxio.music.models.Album
class AlbumDataAdapter : ListAdapter<Album, LibraryViewHolder>(DiffCallback) {
var data = listOf<Album>()
set(newData) {
field = newData
submitList(data)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LibraryViewHolder {
return LibraryViewHolder(
LibraryItemBinding.inflate(LayoutInflater.from(parent.context))
)
}
override fun onBindViewHolder(holder: LibraryViewHolder, position: Int) {
val album = getItem(position)
holder.bindAlbum(album)
}
companion object DiffCallback : DiffUtil.ItemCallback<Album>() {
override fun areItemsTheSame(oldItem: Album, newItem: Album): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: Album, newItem: Album): Boolean {
return oldItem.id == newItem.id
}
}
}

View file

@ -0,0 +1,21 @@
package org.oxycblt.auxio.library.recycler
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.LibraryItemBinding
import org.oxycblt.auxio.music.models.Album
import org.oxycblt.auxio.music.models.Artist
class LibraryViewHolder(
private var binding: LibraryItemBinding
) : RecyclerView.ViewHolder(binding.root) {
// Bind the view w/new data
fun bindAlbum(album: Album) {
binding.album = album
binding.executePendingBindings()
}
fun bindArtist(artist: Artist) {
// TODO: Not implemented.
}
}

View file

@ -32,9 +32,9 @@ private val ID3_GENRES = arrayOf<String>(
const val PAREN_FILTER = "()"
// Convert legacy ID3 genres to a named genre
fun intToNamedGenre(genre: String): String {
fun String.toNamedGenre(): String {
// Strip the genres of any parentheses, and convert it to an int
val intGenre = genre.filterNot {
val intGenre = this.filterNot {
PAREN_FILTER.indexOf(it) > -1
}.toInt()

View file

@ -12,12 +12,13 @@ import android.provider.MediaStore.Audio.Artists
import android.provider.MediaStore.Audio.Genres
import android.provider.MediaStore.Audio.Media
import android.util.Log
import org.oxycblt.auxio.music.intToNamedGenre
import org.oxycblt.auxio.music.models.Album
import org.oxycblt.auxio.music.models.Artist
import org.oxycblt.auxio.music.models.Genre
import org.oxycblt.auxio.music.models.Song
import org.oxycblt.auxio.music.toAlbumArtURI
import org.oxycblt.auxio.music.toNamedGenre
import java.io.FileNotFoundException
enum class MusicLoaderResponse {
DONE, FAILURE, NO_MUSIC
@ -87,7 +88,7 @@ class MusicLoader(private val app: Application) {
// convert that to the corresponding ID3 genre. Really hope anyone doesn't have
// a genre that contains parentheses.
if (name.contains(Regex("[()]"))) {
name = intToNamedGenre(name)
name = name.toNamedGenre()
}
genres.add(
@ -193,17 +194,24 @@ class MusicLoader(private val app: Application) {
val year = cursor.getInt(yearIndex)
val numSongs = cursor.getInt(numIndex)
// TODO:
// Album art loading during the initial load isn't really practical for a large amount of albums
// Use glide or something
val artUri = id.toAlbumArtURI()
var cover: Bitmap? = null
// Get the album art through either ImageDecoder or MediaStore depending on the
// version.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
cover = ImageDecoder.decodeBitmap(
ImageDecoder.createSource(resolver, artUri)
)
} else {
cover = MediaStore.Images.Media.getBitmap(resolver, artUri)
try {
cover = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ImageDecoder.decodeBitmap(
ImageDecoder.createSource(resolver, artUri)
)
} else {
MediaStore.Images.Media.getBitmap(resolver, artUri)
}
} catch (noFound: FileNotFoundException) {
cover = null
}
albums.add(

View file

@ -17,14 +17,15 @@
app:layout_constraintTop_toTopOf="parent"
app:title="@string/title_library_fragment" />
<ImageView
android:id="@+id/testAlbum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/library_recycler"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
app:layout_constraintTop_toBottomOf="@+id/toolbar"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="album"
type="org.oxycblt.auxio.music.models.Album" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/albumNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{album.title}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Album Name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -12,7 +12,9 @@
tools:layout="@layout/fragment_loading">
<action
android:id="@+id/action_to_library"
app:destination="@id/libraryFragment" />
app:destination="@id/libraryFragment"
app:popUpTo="@id/loadingFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/libraryFragment"