Add RecyclerView to LibraryFragment
Add a basic RecyclerView to LibraryFragment that shows every album.
This commit is contained in:
parent
37b071de0d
commit
c04a90c3fa
8 changed files with 126 additions and 20 deletions
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>
|
28
app/src/main/res/layout/library_item.xml
Normal file
28
app/src/main/res/layout/library_item.xml
Normal 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>
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue