Update RecyclerView item layouts
Update the song/album items to have the cover art be loaded by a BindingAdapter, and remove unnecessary chains.
This commit is contained in:
parent
53710ca3f0
commit
c8f7419833
12 changed files with 50 additions and 56 deletions
|
@ -46,7 +46,7 @@ dependencies {
|
||||||
// Kotlin
|
// Kotlin
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
|
||||||
// Support
|
// --- SUPPORT ---
|
||||||
implementation 'androidx.core:core-ktx:1.3.1'
|
implementation 'androidx.core:core-ktx:1.3.1'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
||||||
|
@ -56,21 +56,15 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
||||||
|
|
||||||
|
// Lifecycle
|
||||||
|
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
||||||
|
|
||||||
// Viewpager
|
// Viewpager
|
||||||
implementation 'androidx.viewpager2:viewpager2:1.0.0'
|
implementation 'androidx.viewpager2:viewpager2:1.0.0'
|
||||||
|
|
||||||
|
// --- THIRD PARTY ---
|
||||||
// Image loading
|
// Image loading
|
||||||
implementation("io.coil-kt:coil:0.12.0")
|
implementation 'io.coil-kt:coil:0.12.0'
|
||||||
|
|
||||||
/*
|
|
||||||
// Room Database
|
|
||||||
def room_version = "2.2.5"
|
|
||||||
kapt "androidx.room:room-compiler:$room_version"
|
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Lifecycle
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
|
||||||
|
|
||||||
// Lint
|
// Lint
|
||||||
ktlint "com.pinterest:ktlint:0.37.2"
|
ktlint "com.pinterest:ktlint:0.37.2"
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.oxycblt.auxio
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
// AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Activity Created.")
|
Log.d(this::class.simpleName, "Activity Created.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ class MainFragment : Fragment() {
|
||||||
private fun getFragment(pos: Int): Fragment {
|
private fun getFragment(pos: Int): Fragment {
|
||||||
if (shownFragments.contains(pos)) {
|
if (shownFragments.contains(pos)) {
|
||||||
return when (pos) {
|
return when (pos) {
|
||||||
1 -> libraryFragment
|
0 -> libraryFragment
|
||||||
0 -> songsFragment
|
1 -> songsFragment
|
||||||
|
|
||||||
else -> libraryFragment
|
else -> libraryFragment
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ class MainFragment : Fragment() {
|
||||||
override fun getItemCount(): Int = shownFragments.size
|
override fun getItemCount(): Int = shownFragments.size
|
||||||
|
|
||||||
override fun createFragment(position: Int): Fragment {
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
Log.d(this::class.simpleName, "Switching to fragment $position.")
|
||||||
return getFragment(position)
|
return getFragment(position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
||||||
import org.oxycblt.auxio.recycler.adapters.AlbumDataAdapter
|
import org.oxycblt.auxio.recycler.adapters.AlbumAdapter
|
||||||
import org.oxycblt.auxio.recycler.applyDivider
|
import org.oxycblt.auxio.recycler.applyDivider
|
||||||
|
|
||||||
class LibraryFragment : Fragment() {
|
class LibraryFragment : Fragment() {
|
||||||
|
@ -28,7 +28,7 @@ class LibraryFragment : Fragment() {
|
||||||
inflater, R.layout.fragment_library, container, false
|
inflater, R.layout.fragment_library, container, false
|
||||||
)
|
)
|
||||||
|
|
||||||
val adapter = AlbumDataAdapter(libraryModel.albums.value!!)
|
val adapter = AlbumAdapter(libraryModel.albums.value!!)
|
||||||
|
|
||||||
binding.libraryRecycler.adapter = adapter
|
binding.libraryRecycler.adapter = adapter
|
||||||
binding.libraryRecycler.applyDivider()
|
binding.libraryRecycler.applyDivider()
|
||||||
|
|
|
@ -3,8 +3,10 @@ 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.load
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.music.models.Album
|
import org.oxycblt.auxio.music.models.Album
|
||||||
import org.oxycblt.auxio.music.models.Song
|
import org.oxycblt.auxio.music.models.Song
|
||||||
|
@ -62,6 +64,25 @@ fun Long.toAlbumArtURI(): Uri {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the cover art
|
||||||
|
@BindingAdapter("coverArt")
|
||||||
|
fun ImageView.getCoverArt(any: Any) {
|
||||||
|
val uri = when (any) {
|
||||||
|
is Song -> any.album.coverUri
|
||||||
|
is Album -> any.coverUri
|
||||||
|
|
||||||
|
// TODO: Artist images
|
||||||
|
|
||||||
|
else -> Uri.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
load(uri) {
|
||||||
|
crossfade(true)
|
||||||
|
placeholder(android.R.color.transparent)
|
||||||
|
error(android.R.color.transparent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Format the amount of songs in an album
|
// Format the amount of songs in an album
|
||||||
@BindingAdapter("songCount")
|
@BindingAdapter("songCount")
|
||||||
fun TextView.getAlbumSongs(album: Album) {
|
fun TextView.getAlbumSongs(album: Album) {
|
||||||
|
@ -71,13 +92,3 @@ fun TextView.getAlbumSongs(album: Album) {
|
||||||
context.getString(R.string.format_multi_song_count, album.numSongs.toString())
|
context.getString(R.string.format_multi_song_count, album.numSongs.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the artist/album data for a song
|
|
||||||
@BindingAdapter("songData")
|
|
||||||
fun TextView.getSongData(song: Song) {
|
|
||||||
text = context.getString(
|
|
||||||
R.string.format_song_data,
|
|
||||||
song.album.artist.name,
|
|
||||||
song.album.title
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,13 +7,15 @@ import org.oxycblt.auxio.databinding.AlbumItemBinding
|
||||||
import org.oxycblt.auxio.music.models.Album
|
import org.oxycblt.auxio.music.models.Album
|
||||||
import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
|
import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
|
||||||
|
|
||||||
class AlbumDataAdapter(val data: List<Album>) : RecyclerView.Adapter<AlbumViewHolder>() {
|
class AlbumAdapter(private val data: List<Album>) : RecyclerView.Adapter<AlbumViewHolder>() {
|
||||||
|
|
||||||
override fun getItemCount(): Int = data.size
|
override fun getItemCount(): Int = data.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumViewHolder {
|
||||||
return AlbumViewHolder(
|
return AlbumViewHolder(
|
||||||
AlbumItemBinding.inflate(LayoutInflater.from(parent.context))
|
AlbumItemBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.oxycblt.auxio.databinding.SongItemBinding
|
||||||
import org.oxycblt.auxio.music.models.Song
|
import org.oxycblt.auxio.music.models.Song
|
||||||
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
|
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
|
||||||
|
|
||||||
class SongDataAdapter(val data: List<Song>) : RecyclerView.Adapter<SongViewHolder>() {
|
class SongAdapter(private val data: List<Song>) : RecyclerView.Adapter<SongViewHolder>() {
|
||||||
|
|
||||||
override fun getItemCount(): Int = data.size
|
override fun getItemCount(): Int = data.size
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.oxycblt.auxio.recycler.viewholders
|
package org.oxycblt.auxio.recycler.viewholders
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
|
||||||
import org.oxycblt.auxio.databinding.SongItemBinding
|
import org.oxycblt.auxio.databinding.SongItemBinding
|
||||||
import org.oxycblt.auxio.music.models.Song
|
import org.oxycblt.auxio.music.models.Song
|
||||||
|
|
||||||
|
@ -14,13 +13,6 @@ class SongViewHolder(
|
||||||
fun bind(song: Song) {
|
fun bind(song: Song) {
|
||||||
binding.song = song
|
binding.song = song
|
||||||
|
|
||||||
// Load the album cover
|
|
||||||
binding.cover.load(song.album.coverUri) {
|
|
||||||
crossfade(true)
|
|
||||||
placeholder(android.R.color.transparent)
|
|
||||||
error(android.R.color.transparent)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.executePendingBindings()
|
binding.executePendingBindings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
||||||
import org.oxycblt.auxio.recycler.adapters.SongDataAdapter
|
import org.oxycblt.auxio.recycler.adapters.SongAdapter
|
||||||
import org.oxycblt.auxio.recycler.applyDivider
|
import org.oxycblt.auxio.recycler.applyDivider
|
||||||
|
|
||||||
class SongsFragment : Fragment() {
|
class SongsFragment : Fragment() {
|
||||||
|
@ -28,8 +28,7 @@ class SongsFragment : Fragment() {
|
||||||
inflater, R.layout.fragment_songs, container, false
|
inflater, R.layout.fragment_songs, container, false
|
||||||
)
|
)
|
||||||
|
|
||||||
val adapter = SongDataAdapter(songsModel.songs.value!!)
|
binding.songRecycler.adapter = SongAdapter(songsModel.songs.value!!)
|
||||||
binding.songRecycler.adapter = adapter
|
|
||||||
binding.songRecycler.applyDivider()
|
binding.songRecycler.applyDivider()
|
||||||
binding.songRecycler.setHasFixedSize(true)
|
binding.songRecycler.setHasFixedSize(true)
|
||||||
|
|
||||||
|
|
|
@ -23,20 +23,19 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:coverArt="@{album}"
|
||||||
tools:src="@tools:sample/backgrounds/scenic" />
|
tools:src="@tools:sample/backgrounds/scenic" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/album_name"
|
android:id="@+id/album_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/margin_medium"
|
|
||||||
android:text="@{album.title}"
|
android:text="@{album.title}"
|
||||||
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/song_count"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/cover"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="Album Name" />
|
tools:text="Album Name" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -48,7 +47,6 @@
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/cover"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/album_name"
|
|
||||||
app:songCount="@{album}"
|
app:songCount="@{album}"
|
||||||
tools:text="10 Songs" />
|
tools:text="10 Songs" />
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
android:layout_width="@dimen/cover_size_compact"
|
android:layout_width="@dimen/cover_size_compact"
|
||||||
android:layout_height="@dimen/cover_size_compact"
|
android:layout_height="@dimen/cover_size_compact"
|
||||||
android:contentDescription="@{@string/description_cover_art + song.album.title}"
|
android:contentDescription="@{@string/description_cover_art + song.album.title}"
|
||||||
|
app:coverArt="@{song}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
@ -29,27 +30,24 @@
|
||||||
android:id="@+id/song_name"
|
android:id="@+id/song_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/margin_medium"
|
|
||||||
android:text="@{song.title}"
|
android:text="@{song.title}"
|
||||||
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/song_data"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/cover"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="Song Name" />
|
tools:text="Song Name" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/song_data"
|
android:id="@+id/song_info"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/margin_medium"
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
|
android:text="@{@string/format_song_info(song.album.title, song.album.artist.name)}"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/cover"
|
app:layout_constraintStart_toEndOf="@+id/cover"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
|
||||||
app:songData="@{song}"
|
|
||||||
tools:text="Artist / Album" />
|
tools:text="Artist / Album" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Auxio</string>
|
<string name="app_name">Auxio</string>
|
||||||
|
|
||||||
|
<string name="title_library_fragment">Library</string>
|
||||||
|
<string name="title_all_songs">All Songs</string>
|
||||||
|
|
||||||
<string name="error_no_music">No music found.</string>
|
<string name="error_no_music">No music found.</string>
|
||||||
<string name="error_music_load_failed">Music loading failed.</string>
|
<string name="error_music_load_failed">Music loading failed.</string>
|
||||||
|
|
||||||
|
@ -9,10 +12,7 @@
|
||||||
<string name="label_single_song">1 Song</string>
|
<string name="label_single_song">1 Song</string>
|
||||||
|
|
||||||
<string name="format_multi_song_count">%s Songs</string>
|
<string name="format_multi_song_count">%s Songs</string>
|
||||||
<string name="format_song_data">%s / %s</string>
|
<string name="format_song_info">%s / %s</string>
|
||||||
|
|
||||||
<string name="title_library_fragment">Library</string>
|
|
||||||
<string name="title_all_songs">All Songs</string>
|
|
||||||
|
|
||||||
<string name="description_cover_art">Cover art for </string>
|
<string name="description_cover_art">Cover art for </string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue