From f541504e07d27c6ee289c07b1273a2e8fe110e8d Mon Sep 17 00:00:00 2001 From: Hardcore Sushi Date: Sat, 9 Apr 2022 20:13:39 +0200 Subject: [PATCH] Refactor RecyclerView adapters --- .../adapters/ExplorerElementAdapter.kt | 83 +++++-------------- .../droidfs/adapters/SelectableAdapter.kt | 76 +++++++++++++++++ .../droidfs/adapters/VolumeAdapter.kt | 72 +++------------- 3 files changed, 111 insertions(+), 120 deletions(-) create mode 100644 app/src/main/java/sushi/hardcore/droidfs/adapters/SelectableAdapter.kt diff --git a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt index 22d9f31..55b9c72 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt @@ -22,7 +22,6 @@ import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.util.PathUtils import java.text.DateFormat import java.util.* -import kotlin.collections.HashSet class ExplorerElementAdapter( val activity: AppCompatActivity, @@ -30,7 +29,7 @@ class ExplorerElementAdapter( val onExplorerElementClick: (Int) -> Unit, val onExplorerElementLongClick: (Int) -> Unit, val thumbnailMaxSize: Long, -) : RecyclerView.Adapter() { +) : SelectableAdapter() { val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault()) var explorerElements = listOf() @SuppressLint("NotifyDataSetChanged") @@ -39,7 +38,6 @@ class ExplorerElementAdapter( thumbnailsCache?.evictAll() notifyDataSetChanged() } - var selectedItems: MutableSet = HashSet() var isUsingListLayout = true private var thumbnailsCache: LruCache? = null @@ -49,56 +47,32 @@ class ExplorerElementAdapter( } } - override fun getItemCount(): Int { - return explorerElements.size + override fun getItems(): List { + return explorerElements } - private fun toggleSelection(position: Int): Boolean { - if (!explorerElements[position].isParentFolder) { - if (selectedItems.contains(position)) { - selectedItems.remove(position) - } else { - selectedItems.add(position) - return true - } - } - return false - } - - private fun onItemClick(position: Int): Boolean { - onExplorerElementClick(position) - if (selectedItems.isNotEmpty()) { - return toggleSelection(position) - } - return false - } - - private fun onItemLongClick(position: Int): Boolean { - onExplorerElementLongClick(position) - return toggleSelection(position) - } - - fun selectAll() { - for (i in explorerElements.indices) { - if (!selectedItems.contains(i) && !explorerElements[i].isParentFolder) { - selectedItems.add(i) - notifyItemChanged(i) - } - } - } - - fun unSelectAll(notifyChange: Boolean) { - if (notifyChange) { - val whatWasSelected = selectedItems - selectedItems = HashSet() - whatWasSelected.forEach { - notifyItemChanged(it) - } + override fun toggleSelection(position: Int): Boolean { + return if (!explorerElements[position].isParentFolder) { + super.toggleSelection(position) } else { - selectedItems.clear() + false } } + override fun onItemClick(position: Int): Boolean { + onExplorerElementClick(position) + return super.onItemClick(position) + } + + override fun onItemLongClick(position: Int): Boolean { + onExplorerElementLongClick(position) + return super.onItemLongClick(position) + } + + override fun isSelectable(position: Int): Boolean { + return !explorerElements[position].isParentFolder + } + open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val textElementName by lazy { itemView.findViewById(R.id.text_element_name) @@ -116,21 +90,9 @@ class ExplorerElementAdapter( itemView.findViewById(R.id.selectable_container) } - protected fun setBackground(isSelected: Boolean) { - itemView.setBackgroundResource(if (isSelected) { R.color.itemSelected } else { 0 }) - } - open fun bind(explorerElement: ExplorerElement, position: Int) { textElementName.text = explorerElement.name - (bindingAdapter as ExplorerElementAdapter?)?.let { adapter -> - selectableContainer.setOnClickListener { - setBackground(adapter.onItemClick(position)) - } - selectableContainer.setOnLongClickListener { - setBackground(adapter.onItemLongClick(position)) - true - } - } + (bindingAdapter as ExplorerElementAdapter?)?.setSelectable(selectableContainer, itemView, position) } } @@ -141,7 +103,6 @@ class ExplorerElementAdapter( (bindingAdapter as ExplorerElementAdapter?)?.let { textElementMtime.text = it.dateFormat.format(explorerElement.mTime) } - setBackground(isSelected) } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/adapters/SelectableAdapter.kt b/app/src/main/java/sushi/hardcore/droidfs/adapters/SelectableAdapter.kt new file mode 100644 index 0000000..115035e --- /dev/null +++ b/app/src/main/java/sushi/hardcore/droidfs/adapters/SelectableAdapter.kt @@ -0,0 +1,76 @@ +package sushi.hardcore.droidfs.adapters + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import sushi.hardcore.droidfs.R + +abstract class SelectableAdapter : RecyclerView.Adapter() { + var selectedItems: MutableSet = HashSet() + + protected abstract fun getItems(): List + + override fun getItemCount(): Int { + return getItems().size + } + + protected open fun toggleSelection(position: Int): Boolean { + return if (selectedItems.contains(position)) { + selectedItems.remove(position) + false + } else { + selectedItems.add(position) + true + } + } + + protected open fun onItemClick(position: Int): Boolean { + if (selectedItems.isNotEmpty()) { + return toggleSelection(position) + } + return false + } + + protected open fun onItemLongClick(position: Int): Boolean { + return toggleSelection(position) + } + + protected open fun isSelectable(position: Int): Boolean { + return true + } + + fun selectAll() { + for (i in getItems().indices) { + if (!selectedItems.contains(i) && isSelectable(i)) { + selectedItems.add(i) + notifyItemChanged(i) + } + } + } + + fun unSelectAll(notifyChange: Boolean) { + if (notifyChange) { + val whatWasSelected = selectedItems + selectedItems = HashSet() + whatWasSelected.forEach { + notifyItemChanged(it) + } + } else { + selectedItems.clear() + } + } + + private fun setBackground(rootView: View, isSelected: Boolean) { + rootView.setBackgroundResource(if (isSelected) R.color.itemSelected else 0) + } + + protected fun setSelectable(element: View, rootView: View, position: Int) { + element.setOnClickListener { + setBackground(rootView, onItemClick(position)) + } + element.setOnLongClickListener { + setBackground(rootView, onItemLongClick(position)) + true + } + setBackground(rootView, selectedItems.contains(position)) + } +} \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/adapters/VolumeAdapter.kt b/app/src/main/java/sushi/hardcore/droidfs/adapters/VolumeAdapter.kt index 11cae97..93ff0ba 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/adapters/VolumeAdapter.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/adapters/VolumeAdapter.kt @@ -19,15 +19,18 @@ class VolumeAdapter( private val showReadOnly: Boolean, private val onVolumeItemClick: (Volume, Int) -> Unit, private val onVolumeItemLongClick: () -> Unit, -) : RecyclerView.Adapter() { +) : SelectableAdapter() { private val inflater: LayoutInflater = LayoutInflater.from(context) lateinit var volumes: List - var selectedItems: MutableSet = HashSet() init { reloadVolumes() } + override fun getItems(): List { + return volumes + } + private fun reloadVolumes() { volumes = if (showReadOnly) { volumeDatabase.getVolumes() @@ -36,28 +39,19 @@ class VolumeAdapter( } } - private fun toggleSelection(position: Int): Boolean { - return if (selectedItems.contains(position)) { - selectedItems.remove(position) - false - } else { - selectedItems.add(position) - true - } - } - - private fun onItemClick(position: Int): Boolean { + override fun onItemClick(position: Int): Boolean { onVolumeItemClick(volumes[position], position) - if (allowSelection && selectedItems.isNotEmpty()) { - return toggleSelection(position) + return if (allowSelection) { + super.onItemClick(position) + } else { + false } - return false } - private fun onItemLongClick(position: Int): Boolean { + override fun onItemLongClick(position: Int): Boolean { onVolumeItemLongClick() return if (allowSelection) - toggleSelection(position) + super.onItemLongClick(position) else false } @@ -67,27 +61,6 @@ class VolumeAdapter( notifyItemChanged(position) } - fun selectAll() { - for (i in volumes.indices) { - if (!selectedItems.contains(i)) { - selectedItems.add(i) - notifyItemChanged(i) - } - } - } - - fun unSelectAll(notifyChange: Boolean) { - if (notifyChange) { - val whatWasSelected = selectedItems - selectedItems = HashSet() - whatWasSelected.forEach { - notifyItemChanged(it) - } - } else { - selectedItems.clear() - } - } - fun refresh() { reloadVolumes() unSelectAll(true) @@ -95,10 +68,6 @@ class VolumeAdapter( inner class VolumeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private fun setBackground(isSelected: Boolean) { - itemView.setBackgroundResource(if (isSelected) R.color.itemSelected else 0) - } - fun bind(position: Int) { val volume = volumes[position] itemView.findViewById(R.id.text_volume_name).text = volume.shortName @@ -123,18 +92,7 @@ class VolumeAdapter( visibility = View.VISIBLE } } - (bindingAdapter as VolumeAdapter?)?.let { adapter -> - itemView.findViewById(R.id.selectable_container).apply { - setOnClickListener { - setBackground(adapter.onItemClick(layoutPosition)) - } - setOnLongClickListener { - setBackground(adapter.onItemLongClick(layoutPosition)) - true - } - } - } - setBackground(selectedItems.contains(position)) + setSelectable(itemView.findViewById(R.id.selectable_container), itemView, layoutPosition) } } @@ -146,8 +104,4 @@ class VolumeAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { (holder as VolumeViewHolder).bind(position) } - - override fun getItemCount(): Int { - return volumes.size - } } \ No newline at end of file