forked from hardcoresushi/DroidFS
Refactor RecyclerView adapters
This commit is contained in:
parent
4de5b41102
commit
f541504e07
@ -22,7 +22,6 @@ import sushi.hardcore.droidfs.explorers.ExplorerElement
|
|||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.PathUtils
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashSet
|
|
||||||
|
|
||||||
class ExplorerElementAdapter(
|
class ExplorerElementAdapter(
|
||||||
val activity: AppCompatActivity,
|
val activity: AppCompatActivity,
|
||||||
@ -30,7 +29,7 @@ class ExplorerElementAdapter(
|
|||||||
val onExplorerElementClick: (Int) -> Unit,
|
val onExplorerElementClick: (Int) -> Unit,
|
||||||
val onExplorerElementLongClick: (Int) -> Unit,
|
val onExplorerElementLongClick: (Int) -> Unit,
|
||||||
val thumbnailMaxSize: Long,
|
val thumbnailMaxSize: Long,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : SelectableAdapter<ExplorerElement>() {
|
||||||
val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
|
val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
|
||||||
var explorerElements = listOf<ExplorerElement>()
|
var explorerElements = listOf<ExplorerElement>()
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
@ -39,7 +38,6 @@ class ExplorerElementAdapter(
|
|||||||
thumbnailsCache?.evictAll()
|
thumbnailsCache?.evictAll()
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
var selectedItems: MutableSet<Int> = HashSet()
|
|
||||||
var isUsingListLayout = true
|
var isUsingListLayout = true
|
||||||
private var thumbnailsCache: LruCache<String, Bitmap>? = null
|
private var thumbnailsCache: LruCache<String, Bitmap>? = null
|
||||||
|
|
||||||
@ -49,54 +47,30 @@ class ExplorerElementAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItems(): List<ExplorerElement> {
|
||||||
return explorerElements.size
|
return explorerElements
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleSelection(position: Int): Boolean {
|
override fun toggleSelection(position: Int): Boolean {
|
||||||
if (!explorerElements[position].isParentFolder) {
|
return if (!explorerElements[position].isParentFolder) {
|
||||||
if (selectedItems.contains(position)) {
|
super.toggleSelection(position)
|
||||||
selectedItems.remove(position)
|
|
||||||
} else {
|
} else {
|
||||||
selectedItems.add(position)
|
false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onItemClick(position: Int): Boolean {
|
override fun onItemClick(position: Int): Boolean {
|
||||||
onExplorerElementClick(position)
|
onExplorerElementClick(position)
|
||||||
if (selectedItems.isNotEmpty()) {
|
return super.onItemClick(position)
|
||||||
return toggleSelection(position)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onItemLongClick(position: Int): Boolean {
|
override fun onItemLongClick(position: Int): Boolean {
|
||||||
onExplorerElementLongClick(position)
|
onExplorerElementLongClick(position)
|
||||||
return toggleSelection(position)
|
return super.onItemLongClick(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectAll() {
|
override fun isSelectable(position: Int): Boolean {
|
||||||
for (i in explorerElements.indices) {
|
return !explorerElements[position].isParentFolder
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
@ -116,21 +90,9 @@ class ExplorerElementAdapter(
|
|||||||
itemView.findViewById(R.id.selectable_container)
|
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) {
|
open fun bind(explorerElement: ExplorerElement, position: Int) {
|
||||||
textElementName.text = explorerElement.name
|
textElementName.text = explorerElement.name
|
||||||
(bindingAdapter as ExplorerElementAdapter?)?.let { adapter ->
|
(bindingAdapter as ExplorerElementAdapter?)?.setSelectable(selectableContainer, itemView, position)
|
||||||
selectableContainer.setOnClickListener {
|
|
||||||
setBackground(adapter.onItemClick(position))
|
|
||||||
}
|
|
||||||
selectableContainer.setOnLongClickListener {
|
|
||||||
setBackground(adapter.onItemLongClick(position))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +103,6 @@ class ExplorerElementAdapter(
|
|||||||
(bindingAdapter as ExplorerElementAdapter?)?.let {
|
(bindingAdapter as ExplorerElementAdapter?)?.let {
|
||||||
textElementMtime.text = it.dateFormat.format(explorerElement.mTime)
|
textElementMtime.text = it.dateFormat.format(explorerElement.mTime)
|
||||||
}
|
}
|
||||||
setBackground(isSelected)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
@ -19,15 +19,18 @@ class VolumeAdapter(
|
|||||||
private val showReadOnly: Boolean,
|
private val showReadOnly: Boolean,
|
||||||
private val onVolumeItemClick: (Volume, Int) -> Unit,
|
private val onVolumeItemClick: (Volume, Int) -> Unit,
|
||||||
private val onVolumeItemLongClick: () -> Unit,
|
private val onVolumeItemLongClick: () -> Unit,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : SelectableAdapter<Volume>() {
|
||||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
lateinit var volumes: List<Volume>
|
lateinit var volumes: List<Volume>
|
||||||
var selectedItems: MutableSet<Int> = HashSet()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
reloadVolumes()
|
reloadVolumes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getItems(): List<Volume> {
|
||||||
|
return volumes
|
||||||
|
}
|
||||||
|
|
||||||
private fun reloadVolumes() {
|
private fun reloadVolumes() {
|
||||||
volumes = if (showReadOnly) {
|
volumes = if (showReadOnly) {
|
||||||
volumeDatabase.getVolumes()
|
volumeDatabase.getVolumes()
|
||||||
@ -36,28 +39,19 @@ class VolumeAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleSelection(position: Int): Boolean {
|
override fun onItemClick(position: Int): Boolean {
|
||||||
return if (selectedItems.contains(position)) {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
selectedItems.add(position)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onItemClick(position: Int): Boolean {
|
|
||||||
onVolumeItemClick(volumes[position], position)
|
onVolumeItemClick(volumes[position], position)
|
||||||
if (allowSelection && selectedItems.isNotEmpty()) {
|
return if (allowSelection) {
|
||||||
return toggleSelection(position)
|
super.onItemClick(position)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onItemLongClick(position: Int): Boolean {
|
override fun onItemLongClick(position: Int): Boolean {
|
||||||
onVolumeItemLongClick()
|
onVolumeItemLongClick()
|
||||||
return if (allowSelection)
|
return if (allowSelection)
|
||||||
toggleSelection(position)
|
super.onItemLongClick(position)
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -67,27 +61,6 @@ class VolumeAdapter(
|
|||||||
notifyItemChanged(position)
|
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() {
|
fun refresh() {
|
||||||
reloadVolumes()
|
reloadVolumes()
|
||||||
unSelectAll(true)
|
unSelectAll(true)
|
||||||
@ -95,10 +68,6 @@ class VolumeAdapter(
|
|||||||
|
|
||||||
inner class VolumeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
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) {
|
fun bind(position: Int) {
|
||||||
val volume = volumes[position]
|
val volume = volumes[position]
|
||||||
itemView.findViewById<TextView>(R.id.text_volume_name).text = volume.shortName
|
itemView.findViewById<TextView>(R.id.text_volume_name).text = volume.shortName
|
||||||
@ -123,18 +92,7 @@ class VolumeAdapter(
|
|||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(bindingAdapter as VolumeAdapter?)?.let { adapter ->
|
setSelectable(itemView.findViewById<LinearLayout>(R.id.selectable_container), itemView, layoutPosition)
|
||||||
itemView.findViewById<LinearLayout>(R.id.selectable_container).apply {
|
|
||||||
setOnClickListener {
|
|
||||||
setBackground(adapter.onItemClick(layoutPosition))
|
|
||||||
}
|
|
||||||
setOnLongClickListener {
|
|
||||||
setBackground(adapter.onItemLongClick(layoutPosition))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setBackground(selectedItems.contains(position))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,8 +104,4 @@ class VolumeAdapter(
|
|||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
(holder as VolumeViewHolder).bind(position)
|
(holder as VolumeViewHolder).bind(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return volumes.size
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user