Refactor RecyclerView adapters

This commit is contained in:
Matéo Duparc 2022-04-09 20:13:39 +02:00
parent 4de5b41102
commit f541504e07
Signed by untrusted user: hardcoresushi
GPG Key ID: AFE384344A45E13A
3 changed files with 111 additions and 120 deletions

View File

@ -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<RecyclerView.ViewHolder>() {
) : SelectableAdapter<ExplorerElement>() {
val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
var explorerElements = listOf<ExplorerElement>()
@SuppressLint("NotifyDataSetChanged")
@ -39,7 +38,6 @@ class ExplorerElementAdapter(
thumbnailsCache?.evictAll()
notifyDataSetChanged()
}
var selectedItems: MutableSet<Int> = HashSet()
var isUsingListLayout = true
private var thumbnailsCache: LruCache<String, Bitmap>? = null
@ -49,54 +47,30 @@ class ExplorerElementAdapter(
}
}
override fun getItemCount(): Int {
return explorerElements.size
override fun getItems(): List<ExplorerElement> {
return explorerElements
}
private fun toggleSelection(position: Int): Boolean {
if (!explorerElements[position].isParentFolder) {
if (selectedItems.contains(position)) {
selectedItems.remove(position)
override fun toggleSelection(position: Int): Boolean {
return if (!explorerElements[position].isParentFolder) {
super.toggleSelection(position)
} else {
selectedItems.add(position)
return true
false
}
}
return false
}
private fun onItemClick(position: Int): Boolean {
override fun onItemClick(position: Int): Boolean {
onExplorerElementClick(position)
if (selectedItems.isNotEmpty()) {
return toggleSelection(position)
}
return false
return super.onItemClick(position)
}
private fun onItemLongClick(position: Int): Boolean {
override fun onItemLongClick(position: Int): Boolean {
onExplorerElementLongClick(position)
return toggleSelection(position)
return super.onItemLongClick(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)
}
} else {
selectedItems.clear()
}
override fun isSelectable(position: Int): Boolean {
return !explorerElements[position].isParentFolder
}
open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
@ -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)
}
}

View File

@ -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<T> : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var selectedItems: MutableSet<Int> = HashSet()
protected abstract fun getItems(): List<T>
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))
}
}

View File

@ -19,15 +19,18 @@ class VolumeAdapter(
private val showReadOnly: Boolean,
private val onVolumeItemClick: (Volume, Int) -> Unit,
private val onVolumeItemLongClick: () -> Unit,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
) : SelectableAdapter<Volume>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
lateinit var volumes: List<Volume>
var selectedItems: MutableSet<Int> = HashSet()
init {
reloadVolumes()
}
override fun getItems(): List<Volume> {
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<TextView>(R.id.text_volume_name).text = volume.shortName
@ -123,18 +92,7 @@ class VolumeAdapter(
visibility = View.VISIBLE
}
}
(bindingAdapter as VolumeAdapter?)?.let { adapter ->
itemView.findViewById<LinearLayout>(R.id.selectable_container).apply {
setOnClickListener {
setBackground(adapter.onItemClick(layoutPosition))
}
setOnLongClickListener {
setBackground(adapter.onItemLongClick(layoutPosition))
true
}
}
}
setBackground(selectedItems.contains(position))
setSelectable(itemView.findViewById<LinearLayout>(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
}
}