Create a new SelectMusicFolderViewHolder instance when the Adapter is recreated,

instead of reusing an old one. This lead to a crash.

Also make the AlbumList use the correct placeholder,
remove an unused resource file, and update the placeholder to look less clumsy.
This commit is contained in:
tzugen 2021-05-17 17:14:04 +02:00
parent 2cf80707f7
commit 5f08e7e7cd
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
10 changed files with 201 additions and 199 deletions

View File

@ -61,10 +61,10 @@ class AlbumListFragment : GenericListFragment<MusicDirectory.Entry, AlbumRowAdap
override val viewAdapter: AlbumRowAdapter by lazy { override val viewAdapter: AlbumRowAdapter by lazy {
AlbumRowAdapter( AlbumRowAdapter(
liveDataItems.value ?: listOf(), liveDataItems.value ?: listOf(),
selectFolderHeader,
{ entry -> onItemClick(entry) }, { entry -> onItemClick(entry) },
{ menuItem, entry -> onContextMenuItemSelected(menuItem, entry) }, { menuItem, entry -> onContextMenuItemSelected(menuItem, entry) },
imageLoaderProvider.getImageLoader() imageLoaderProvider.getImageLoader(),
onMusicFolderUpdate
) )
} }

View File

@ -7,10 +7,8 @@
package org.moire.ultrasonic.fragment package org.moire.ultrasonic.fragment
import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
@ -18,22 +16,21 @@ import androidx.recyclerview.widget.RecyclerView
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.util.ImageLoader import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.view.SelectMusicFolderView
/** /**
* Creates a Row in a RecyclerView which contains the details of an Album * Creates a Row in a RecyclerView which contains the details of an Album
*/ */
class AlbumRowAdapter( class AlbumRowAdapter(
albumList: List<MusicDirectory.Entry>, albumList: List<MusicDirectory.Entry>,
private var selectFolderHeader: SelectMusicFolderView?,
onItemClick: (MusicDirectory.Entry) -> Unit, onItemClick: (MusicDirectory.Entry) -> Unit,
onContextMenuClick: (MenuItem, MusicDirectory.Entry) -> Boolean, onContextMenuClick: (MenuItem, MusicDirectory.Entry) -> Boolean,
private val imageLoader: ImageLoader private val imageLoader: ImageLoader,
onMusicFolderUpdate: (String?) -> Unit
) : GenericRowAdapter<MusicDirectory.Entry>( ) : GenericRowAdapter<MusicDirectory.Entry>(
selectFolderHeader,
onItemClick, onItemClick,
onContextMenuClick, onContextMenuClick,
imageLoader imageLoader,
onMusicFolderUpdate
) { ) {
override var itemList = albumList override var itemList = albumList
@ -48,20 +45,8 @@ class AlbumRowAdapter(
super.notifyDataSetChanged() super.notifyDataSetChanged()
} }
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
if (viewType == TYPE_ITEM) {
val row = LayoutInflater.from(parent.context)
.inflate(layout, parent, false)
return AlbumViewHolder(row)
}
return selectFolderHeader!!
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is AlbumViewHolder) { if (holder is ViewHolder) {
val listPosition = if (selectFolderHeader != null) position - 1 else position val listPosition = if (selectFolderHeader != null) position - 1 else position
val entry = itemList[listPosition] val entry = itemList[listPosition]
holder.album.text = entry.title holder.album.text = entry.title
@ -73,7 +58,7 @@ class AlbumRowAdapter(
imageLoader.loadImage( imageLoader.loadImage(
holder.coverArt, holder.coverArt,
MusicDirectory.Entry().apply { coverArt = holder.coverArtId }, MusicDirectory.Entry().apply { coverArt = holder.coverArtId },
false, 0, false, true, R.drawable.ic_contact_picture false, 0, false, true, R.drawable.unknown_album
) )
} }
} }
@ -88,13 +73,20 @@ class AlbumRowAdapter(
/** /**
* Holds the view properties of an Item row * Holds the view properties of an Item row
*/ */
class AlbumViewHolder( class ViewHolder(
itemView: View view: View
) : RecyclerView.ViewHolder(itemView) { ) : RecyclerView.ViewHolder(view) {
var album: TextView = itemView.findViewById(R.id.album_title) var album: TextView = view.findViewById(R.id.album_title)
var artist: TextView = itemView.findViewById(R.id.album_artist) var artist: TextView = view.findViewById(R.id.album_artist)
var details: LinearLayout = itemView.findViewById(R.id.row_album_details) var details: LinearLayout = view.findViewById(R.id.row_album_details)
var coverArt: ImageView = itemView.findViewById(R.id.album_coverart) var coverArt: ImageView = view.findViewById(R.id.album_coverart)
var coverArtId: String? = null var coverArtId: String? = null
} }
/**
* Creates an instance of our ViewHolder class
*/
override fun newViewHolder(view: View): RecyclerView.ViewHolder {
return ViewHolder(view)
}
} }

View File

@ -54,10 +54,10 @@ class ArtistListFragment : GenericListFragment<Artist, ArtistRowAdapter>() {
override val viewAdapter: ArtistRowAdapter by lazy { override val viewAdapter: ArtistRowAdapter by lazy {
ArtistRowAdapter( ArtistRowAdapter(
liveDataItems.value ?: listOf(), liveDataItems.value ?: listOf(),
selectFolderHeader,
{ entry -> onItemClick(entry) }, { entry -> onItemClick(entry) },
{ menuItem, entry -> onContextMenuItemSelected(menuItem, entry) }, { menuItem, entry -> onContextMenuItemSelected(menuItem, entry) },
imageLoaderProvider.getImageLoader() imageLoaderProvider.getImageLoader(),
onMusicFolderUpdate
) )
} }
} }

View File

@ -17,22 +17,21 @@ import org.moire.ultrasonic.domain.Artist
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.util.ImageLoader import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.util.Util import org.moire.ultrasonic.util.Util
import org.moire.ultrasonic.view.SelectMusicFolderView
/** /**
* Creates a Row in a RecyclerView which contains the details of an Artist * Creates a Row in a RecyclerView which contains the details of an Artist
*/ */
class ArtistRowAdapter( class ArtistRowAdapter(
artistList: List<Artist>, artistList: List<Artist>,
private var selectFolderHeader: SelectMusicFolderView?,
onItemClick: (Artist) -> Unit, onItemClick: (Artist) -> Unit,
onContextMenuClick: (MenuItem, Artist) -> Boolean, onContextMenuClick: (MenuItem, Artist) -> Boolean,
private val imageLoader: ImageLoader private val imageLoader: ImageLoader,
onMusicFolderUpdate: (String?) -> Unit
) : GenericRowAdapter<Artist>( ) : GenericRowAdapter<Artist>(
selectFolderHeader,
onItemClick, onItemClick,
onContextMenuClick, onContextMenuClick,
imageLoader imageLoader,
onMusicFolderUpdate
), ),
SectionedAdapter { SectionedAdapter {
@ -51,7 +50,7 @@ class ArtistRowAdapter(
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ItemViewHolder) { if (holder is ViewHolder) {
val listPosition = if (selectFolderHeader != null) position - 1 else position val listPosition = if (selectFolderHeader != null) position - 1 else position
holder.textView.text = itemList[listPosition].name holder.textView.text = itemList[listPosition].name
holder.section.text = getSectionForArtist(listPosition) holder.section.text = getSectionForArtist(listPosition)
@ -101,4 +100,11 @@ class ArtistRowAdapter(
if (!section.isLetter()) section = '#' if (!section.isLetter()) section = '#'
return section.toString() return section.toString()
} }
/**
* Creates an instance of our ViewHolder class
*/
override fun newViewHolder(view: View): RecyclerView.ViewHolder {
return ViewHolder(view)
}
} }

View File

@ -88,15 +88,25 @@ abstract class GenericListFragment<T : GenericEntry, TA : GenericRowAdapter<T>>
/** /**
* The observer to be called if the available music folders have changed * The observer to be called if the available music folders have changed
*/ */
val musicFolderObserver = { changedFolders: List<MusicFolder> -> @Suppress("CommentOverPrivateProperty")
viewAdapter.notifyDataSetChanged() private val musicFolderObserver = { folders: List<MusicFolder> ->
selectFolderHeader?.setData( viewAdapter.setFolderList(folders, listModel.activeServer.musicFolderId)
activeServerProvider.getActiveServer().musicFolderId,
changedFolders
)
Unit Unit
} }
/**
* What to do when the user has modified the folder filter
*/
val onMusicFolderUpdate = { selectedFolderId: String? ->
if (!listModel.isOffline()) {
val currentSetting = listModel.activeServer
currentSetting.musicFolderId = selectedFolderId
serverSettingsModel.updateItem(currentSetting)
}
viewAdapter.notifyDataSetChanged()
listModel.refresh(refreshListView!!, arguments)
}
/** /**
* Whether to show the folder selector * Whether to show the folder selector
*/ */
@ -142,27 +152,15 @@ abstract class GenericListFragment<T : GenericEntry, TA : GenericRowAdapter<T>>
// Create a View Manager // Create a View Manager
viewManager = LinearLayoutManager(this.context) viewManager = LinearLayoutManager(this.context)
// Show folder selector UI if enabled
if (showFolderHeader()) {
selectFolderHeader = SelectMusicFolderView(
requireContext(), view as ViewGroup
) { selectedFolderId ->
if (!listModel.isOffline()) {
val currentSetting = listModel.activeServer
currentSetting.musicFolderId = selectedFolderId
serverSettingsModel.updateItem(currentSetting)
}
viewAdapter.notifyDataSetChanged()
listModel.refresh(refreshListView!!, arguments)
}
}
// Hook up the view with the manager and the adapter // Hook up the view with the manager and the adapter
listView = view.findViewById<RecyclerView>(recyclerViewId).apply { listView = view.findViewById<RecyclerView>(recyclerViewId).apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = viewAdapter adapter = viewAdapter
} }
// Configure whether to show the folder header
viewAdapter.folderHeaderEnabled = showFolderHeader()
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.util.ImageLoader import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.view.SelectMusicFolderView import org.moire.ultrasonic.view.SelectMusicFolderView
@ -26,16 +27,20 @@ import org.moire.ultrasonic.view.SelectMusicFolderView
* An abstract Adapter, which can be extended to display a List of <T> in a RecyclerView * An abstract Adapter, which can be extended to display a List of <T> in a RecyclerView
*/ */
abstract class GenericRowAdapter<T>( abstract class GenericRowAdapter<T>(
private var selectFolderHeader: SelectMusicFolderView?,
val onItemClick: (T) -> Unit, val onItemClick: (T) -> Unit,
val onContextMenuClick: (MenuItem, T) -> Boolean, val onContextMenuClick: (MenuItem, T) -> Boolean,
private val imageLoader: ImageLoader private val imageLoader: ImageLoader,
private val onMusicFolderUpdate: (String?) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
open var itemList: List<T> = listOf() open var itemList: List<T> = listOf()
protected abstract val layout: Int protected abstract val layout: Int
protected abstract val contextMenuLayout: Int protected abstract val contextMenuLayout: Int
var folderHeaderEnabled: Boolean = true
var selectFolderHeader: SelectMusicFolderView? = null
var musicFolders: List<MusicFolder> = listOf()
var selectedFolder: String? = null
/** /**
* Sets the data to be displayed in the RecyclerView * Sets the data to be displayed in the RecyclerView
*/ */
@ -44,6 +49,25 @@ abstract class GenericRowAdapter<T>(
notifyDataSetChanged() notifyDataSetChanged()
} }
/**
* Sets the content and state of the music folder selector row
*/
fun setFolderList(changedFolders: List<MusicFolder>, selectedId: String?) {
musicFolders = changedFolders
selectedFolder = selectedId
selectFolderHeader?.setData(
selectedFolder,
musicFolders
)
notifyDataSetChanged()
}
open fun newViewHolder(view: View): RecyclerView.ViewHolder {
return ViewHolder(view)
}
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int
@ -51,13 +75,27 @@ abstract class GenericRowAdapter<T>(
if (viewType == TYPE_ITEM) { if (viewType == TYPE_ITEM) {
val row = LayoutInflater.from(parent.context) val row = LayoutInflater.from(parent.context)
.inflate(layout, parent, false) .inflate(layout, parent, false)
return ItemViewHolder(row) return newViewHolder(row)
} else {
val row = LayoutInflater.from(parent.context)
.inflate(
R.layout.select_folder_header, parent, false
)
selectFolderHeader = SelectMusicFolderView(parent.context, row, onMusicFolderUpdate)
if (musicFolders.isNotEmpty()) {
selectFolderHeader?.setData(
selectedFolder,
musicFolders
)
}
return selectFolderHeader!!
} }
return selectFolderHeader!!
} }
override fun onViewRecycled(holder: RecyclerView.ViewHolder) { override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
if ((holder is ItemViewHolder) && (holder.coverArtId != null)) { if ((holder is ViewHolder) && (holder.coverArtId != null)) {
imageLoader.cancel(holder.coverArtId) imageLoader.cancel(holder.coverArtId)
} }
super.onViewRecycled(holder) super.onViewRecycled(holder)
@ -73,7 +111,7 @@ abstract class GenericRowAdapter<T>(
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return if (position == 0 && selectFolderHeader != null) TYPE_HEADER else TYPE_ITEM return if (position == 0 && folderHeaderEnabled) TYPE_HEADER else TYPE_ITEM
} }
internal fun createPopupMenu(view: View, position: Int): Boolean { internal fun createPopupMenu(view: View, position: Int): Boolean {
@ -94,7 +132,7 @@ abstract class GenericRowAdapter<T>(
/** /**
* Holds the view properties of an Item row * Holds the view properties of an Item row
*/ */
class ItemViewHolder( class ViewHolder(
itemView: View itemView: View
) : RecyclerView.ViewHolder(itemView) { ) : RecyclerView.ViewHolder(itemView) {
var section: TextView = itemView.findViewById(R.id.row_section) var section: TextView = itemView.findViewById(R.id.row_section)

View File

@ -34,13 +34,10 @@ import java.util.Random
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.core.component.KoinApiExtension import org.koin.core.component.KoinApiExtension
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
import org.moire.ultrasonic.service.CommunicationErrorHandler import org.moire.ultrasonic.service.CommunicationErrorHandler
@ -57,7 +54,6 @@ import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator
import org.moire.ultrasonic.util.Util import org.moire.ultrasonic.util.Util
import org.moire.ultrasonic.view.AlbumView import org.moire.ultrasonic.view.AlbumView
import org.moire.ultrasonic.view.EntryAdapter import org.moire.ultrasonic.view.EntryAdapter
import org.moire.ultrasonic.view.SelectMusicFolderView
import org.moire.ultrasonic.view.SongView import org.moire.ultrasonic.view.SongView
import timber.log.Timber import timber.log.Timber
@ -71,7 +67,6 @@ class TrackCollectionFragment : Fragment() {
private var refreshAlbumListView: SwipeRefreshLayout? = null private var refreshAlbumListView: SwipeRefreshLayout? = null
private var albumListView: ListView? = null private var albumListView: ListView? = null
private var header: View? = null private var header: View? = null
private var selectFolderHeader: SelectMusicFolderView? = null
private var albumButtons: View? = null private var albumButtons: View? = null
private var emptyView: TextView? = null private var emptyView: TextView? = null
private var selectButton: ImageView? = null private var selectButton: ImageView? = null
@ -95,7 +90,6 @@ class TrackCollectionFragment : Fragment() {
private val imageLoaderProvider: ImageLoaderProvider by inject() private val imageLoaderProvider: ImageLoaderProvider by inject()
private val shareHandler: ShareHandler by inject() private val shareHandler: ShareHandler by inject()
private var cancellationToken: CancellationToken? = null private var cancellationToken: CancellationToken? = null
private val activeServerProvider: ActiveServerProvider by inject()
private val model: TrackCollectionModel by viewModels() private val model: TrackCollectionModel by viewModels()
private val random: Random = SecureRandom() private val random: Random = SecureRandom()
@ -131,19 +125,6 @@ class TrackCollectionFragment : Fragment() {
false false
) )
selectFolderHeader = SelectMusicFolderView(
requireContext(), view as ViewGroup
) { selectedFolderId ->
if (!isOffline()) {
val serverSettingsModel: ServerSettingsModel by viewModel()
val currentSetting = activeServerProvider.getActiveServer()
currentSetting.musicFolderId = selectedFolderId
serverSettingsModel.updateItem(currentSetting)
}
this.updateDisplay(true)
}
model.musicFolders.observe(viewLifecycleOwner, musicFolderObserver)
model.currentDirectory.observe(viewLifecycleOwner, defaultObserver) model.currentDirectory.observe(viewLifecycleOwner, defaultObserver)
model.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver) model.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver)
@ -622,15 +603,6 @@ class TrackCollectionFragment : Fragment() {
mediaPlayerController.unpin(songs) mediaPlayerController.unpin(songs)
} }
private val musicFolderObserver = Observer<List<MusicFolder>> { changedFolders ->
if (changedFolders != null) {
selectFolderHeader!!.setData(
activeServerProvider.getActiveServer().musicFolderId,
changedFolders
)
}
}
private val songsForGenreObserver = Observer<MusicDirectory> { musicDirectory -> private val songsForGenreObserver = Observer<MusicDirectory> { musicDirectory ->
// Hide more button when results are less than album list size // Hide more button when results are less than album list size
@ -726,12 +698,9 @@ class TrackCollectionFragment : Fragment() {
} }
} }
} else { } else {
if (model.showSelectFolderHeader(arguments)) {
if (albumListView!!.headerViewsCount == 0) {
albumListView!!.addHeaderView(selectFolderHeader!!.itemView, null, false)
}
}
// TODO: This code path can be removed when getArtist has been moved to
// AlbumListFragment (getArtist returns the albums of an artist)
pinButton!!.visibility = View.GONE pinButton!!.visibility = View.GONE
unpinButton!!.visibility = View.GONE unpinButton!!.visibility = View.GONE
downloadButton!!.visibility = View.GONE downloadButton!!.visibility = View.GONE

View File

@ -1,89 +1,87 @@
package org.moire.ultrasonic.view package org.moire.ultrasonic.view
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.MenuItem
import android.view.MenuItem import android.view.View
import android.view.ViewGroup import android.widget.LinearLayout
import android.widget.LinearLayout import android.widget.PopupMenu
import android.widget.PopupMenu import android.widget.TextView
import android.widget.TextView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView import org.moire.ultrasonic.R
import org.moire.ultrasonic.R import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.domain.MusicFolder
/**
/** * This little view shows the currently selected Folder (or catalog) on the music server.
* This little view shows the currently selected Folder (or catalog) on the music server. * When clicked it will drop down a list of all available Folders and allow you to
* When clicked it will drop down a list of all available Folders and allow you to * select one. The intended usage is to supply a filter to lists of artists, albums, etc
* select one. The intended usage is to supply a filter to lists of artists, albums, etc */
*/ class SelectMusicFolderView(
class SelectMusicFolderView( private val context: Context,
private val context: Context, view: View,
root: ViewGroup, private val onUpdate: (String?) -> Unit
private val onUpdate: (String?) -> Unit ) : RecyclerView.ViewHolder(view) {
) : RecyclerView.ViewHolder( private var musicFolders: List<MusicFolder> = mutableListOf()
LayoutInflater.from(context).inflate( private var selectedFolderId: String? = null
R.layout.select_folder_header, root, false private val folderName: TextView = itemView.findViewById(R.id.select_folder_name)
) private val layout: LinearLayout = itemView.findViewById(R.id.select_folder_header)
) {
private var musicFolders: List<MusicFolder> = mutableListOf<MusicFolder>() init {
private var selectedFolderId: String? = null folderName.text = context.getString(R.string.select_artist_all_folders)
private val folderName: TextView = itemView.findViewById(R.id.select_folder_name) layout.setOnClickListener { onFolderClick() }
private val layout: LinearLayout = itemView.findViewById(R.id.select_folder_header) }
private val MENU_GROUP_MUSIC_FOLDER = 10
fun setData(selectedId: String?, folders: List<MusicFolder>) {
init { selectedFolderId = selectedId
folderName.text = context.getString(R.string.select_artist_all_folders) musicFolders = folders
layout.setOnClickListener { onFolderClick() } if (selectedFolderId != null) {
} for ((id, name) in musicFolders) {
if (id == selectedFolderId) {
fun setData(selectedId: String?, folders: List<MusicFolder>) { folderName.text = name
selectedFolderId = selectedId break
musicFolders = folders }
if (selectedFolderId != null) { }
for ((id, name) in musicFolders) { } else {
if (id == selectedFolderId) { folderName.text = context.getString(R.string.select_artist_all_folders)
folderName.text = name }
break }
}
} private fun onFolderClick() {
} else { val popup = PopupMenu(context, layout)
folderName.text = context.getString(R.string.select_artist_all_folders)
} var menuItem = popup.menu.add(
} MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders
)
private fun onFolderClick() { if (selectedFolderId == null || selectedFolderId!!.isEmpty()) {
val popup = PopupMenu(context, layout) menuItem.isChecked = true
}
var menuItem = popup.menu.add( musicFolders.forEachIndexed { i, musicFolder ->
MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders val (id, name) = musicFolder
) menuItem = popup.menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, name)
if (selectedFolderId == null || selectedFolderId!!.isEmpty()) { if (id == selectedFolderId) {
menuItem.isChecked = true menuItem.isChecked = true
} }
musicFolders.forEachIndexed { i, musicFolder -> }
val (id, name) = musicFolder
menuItem = popup.menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, name) popup.menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true)
if (id == selectedFolderId) {
menuItem.isChecked = true popup.setOnMenuItemClickListener { item -> onFolderMenuItemSelected(item) }
} popup.show()
} }
popup.menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true) private fun onFolderMenuItemSelected(menuItem: MenuItem): Boolean {
val selectedFolder = if (menuItem.itemId == -1) null else musicFolders[menuItem.itemId]
popup.setOnMenuItemClickListener { item -> onFolderMenuItemSelected(item) } val musicFolderName = selectedFolder?.name
popup.show() ?: context.getString(R.string.select_artist_all_folders)
} selectedFolderId = selectedFolder?.id
private fun onFolderMenuItemSelected(menuItem: MenuItem): Boolean { menuItem.isChecked = true
val selectedFolder = if (menuItem.itemId == -1) null else musicFolders[menuItem.itemId] folderName.text = musicFolderName
val musicFolderName = selectedFolder?.name onUpdate(selectedFolderId)
?: context.getString(R.string.select_artist_all_folders)
selectedFolderId = selectedFolder?.id return true
}
menuItem.isChecked = true
folderName.text = musicFolderName companion object {
onUpdate(selectedFolderId) const val MENU_GROUP_MUSIC_FOLDER = 10
}
return true }
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp" android:width="200dp"
android:height="100dp" android:height="200dp"
android:viewportWidth="24" android:viewportWidth="100"
android:viewportHeight="24"> android:viewportHeight="100">
<path <path
android:fillColor="#000" android:pathData="M0,0h100v100h-100z"
android:pathData="M0 0 L24 0 L24 24 L0 24 Z"/> android:fillColor="#1a1a1a"/>
<path <path
android:fillColor="#FFF" android:pathData="M42.415,84.787C49.463,84.53 55.166,77.789 54.75,70.704 55.614,58.35 56.479,45.979 57.342,33.633c0.513,-0.518 1.407,0.72 1.903,0.815 5.393,3.785 9.987,9.62 9.845,16.528 -0.003,5.402 -1.991,10.554 -4.162,15.413C71.552,59.26 74.281,48.374 70.666,39.149 68.858,33.816 64.197,30.278 61.795,25.279A26.452,26.452 0,0 1,58.5 14.397c-0.343,-0.816 -1.323,-0.945 -2.094,-0.999l-0.017,-0.001c-2.434,-0.17 -2.216,1.472 -2.331,3.117l-3.274,46.814c0,0 -1.255,-0.207 -2.188,-0.272 -7.098,-0.965 -15.202,3.666 -16.437,11.095 -1.246,5.877 4.638,11.171 10.257,10.635z"
android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/> android:strokeWidth="0.85"
android:fillColor="#ffffff"/>
</vector> </vector>