refactor ItemsAdapter

This commit is contained in:
tibbi 2017-06-19 23:26:19 +02:00
parent 8c9f7bf050
commit dc595c5a0e
2 changed files with 105 additions and 74 deletions

View File

@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.support.v7.view.ActionMode import android.support.v7.view.ActionMode
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.util.SparseArray
import android.view.* import android.view.*
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
import com.bignerdranch.android.multiselector.MultiSelector import com.bignerdranch.android.multiselector.MultiSelector
@ -28,42 +29,53 @@ import java.util.*
class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDirItem>, val listener: ItemOperationsListener?, val itemClick: (FileDirItem) -> Unit) : class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDirItem>, val listener: ItemOperationsListener?, val itemClick: (FileDirItem) -> Unit) :
RecyclerView.Adapter<ItemsAdapter.ViewHolder>() { RecyclerView.Adapter<ItemsAdapter.ViewHolder>() {
val multiSelector = MultiSelector() val multiSelector = MultiSelector()
val views = ArrayList<View>()
val config = activity.config val config = activity.config
companion object { var actMode: ActionMode? = null
var actMode: ActionMode? = null var itemViews = SparseArray<View>()
val markedItems = HashSet<Int>() val selectedPositions = HashSet<Int>()
var textColor = 0
var itemCnt = 0
lateinit var folderDrawable: Drawable var textColor = activity.config.textColor
lateinit var fileDrawable: Drawable
fun toggleItemSelection(itemView: View, select: Boolean, pos: Int = -1) { lateinit var folderDrawable: Drawable
itemView.item_frame.isSelected = select lateinit var fileDrawable: Drawable
if (pos == -1)
return
if (select) fun toggleItemSelection(select: Boolean, pos: Int) {
markedItems.add(pos) itemViews[pos]?.item_frame?.isSelected = select
else
markedItems.remove(pos) if (select)
selectedPositions.add(pos)
else
selectedPositions.remove(pos)
if (selectedPositions.isEmpty()) {
actMode?.finish()
return
} }
fun updateTitle(cnt: Int) { updateTitle(selectedPositions.size)
actMode?.title = "$cnt / $itemCnt" actMode?.invalidate()
} }
fun updateTitle(cnt: Int) {
actMode?.title = "$cnt / ${mItems.size}"
} }
init { init {
textColor = activity.config.textColor folderDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_folder, textColor)
folderDrawable = activity.resources.getColoredDrawableWithColor(com.simplemobiletools.commons.R.drawable.ic_folder, textColor)
folderDrawable.alpha = 180 folderDrawable.alpha = 180
fileDrawable = activity.resources.getColoredDrawableWithColor(com.simplemobiletools.commons.R.drawable.ic_file, textColor) fileDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_file, textColor)
fileDrawable.alpha = 180 fileDrawable.alpha = 180
itemCnt = mItems.size }
val adapterListener = object : MyAdapterListener {
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
toggleItemSelection(select, position)
}
override fun getSelectedPositions(): HashSet<Int> = selectedPositions
} }
val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) { val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
@ -89,14 +101,16 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean { override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
val menuItem = menu.findItem(R.id.cab_rename) val menuItem = menu.findItem(R.id.cab_rename)
menuItem.isVisible = multiSelector.selectedPositions.size <= 1 menuItem.isVisible = selectedPositions.size <= 1
return true return true
} }
override fun onDestroyActionMode(actionMode: ActionMode?) { override fun onDestroyActionMode(actionMode: ActionMode?) {
super.onDestroyActionMode(actionMode) super.onDestroyActionMode(actionMode)
views.forEach { toggleItemSelection(it, false) } selectedPositions.forEach {
markedItems.clear() itemViews[it]?.isSelected = false
}
selectedPositions.clear()
actMode = null actMode = null
} }
} }
@ -111,12 +125,11 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
} }
private fun showProperties() { private fun showProperties() {
val selections = multiSelector.selectedPositions if (selectedPositions.size <= 1) {
if (selections.size <= 1) { PropertiesDialog(activity, mItems[selectedPositions.first()].path, config.showHidden)
PropertiesDialog(activity, mItems[selections[0]].path, config.showHidden)
} else { } else {
val paths = ArrayList<String>() val paths = ArrayList<String>()
selections.forEach { paths.add(mItems[it].path) } selectedPositions.forEach { paths.add(mItems[it].path) }
PropertiesDialog(activity, paths, config.showHidden) PropertiesDialog(activity, paths, config.showHidden)
} }
} }
@ -142,8 +155,7 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
private fun copyMoveTo(isCopyOperation: Boolean) { private fun copyMoveTo(isCopyOperation: Boolean) {
val files = ArrayList<File>() val files = ArrayList<File>()
val positions = multiSelector.selectedPositions selectedPositions.forEach { files.add(File(mItems[it].path)) }
positions.forEach { files.add(File(mItems[it].path)) }
val source = if (files[0].isFile) files[0].parent else files[0].absolutePath val source = if (files[0].isFile) files[0].parent else files[0].absolutePath
FilePickerDialog(activity, source, false, config.showHidden, true) { FilePickerDialog(activity, source, false, config.showHidden, true) {
@ -158,36 +170,47 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
private fun askConfirmDelete() { private fun askConfirmDelete() {
ConfirmationDialog(activity) { ConfirmationDialog(activity) {
actMode?.finish()
deleteFiles() deleteFiles()
actMode?.finish()
} }
} }
private fun deleteFiles() { private fun deleteFiles() {
val selections = multiSelector.selectedPositions if (selectedPositions.isEmpty())
val files = ArrayList<File>(selections.size) return
val removeFiles = ArrayList<FileDirItem>(selections.size)
activity.handleSAFDialog(File(mItems[selections[0]].path)) { val files = ArrayList<File>(selectedPositions.size)
selections.reverse() val removeFiles = ArrayList<FileDirItem>(selectedPositions.size)
selections.forEach {
activity.handleSAFDialog(File(mItems[selectedPositions.first()].path)) {
selectedPositions.sortedDescending().forEach {
val file = mItems[it] val file = mItems[it]
files.add(File(file.path)) files.add(File(file.path))
removeFiles.add(file) removeFiles.add(file)
notifyItemRemoved(it) notifyItemRemoved(it)
itemViews.put(it, null)
} }
mItems.removeAll(removeFiles) mItems.removeAll(removeFiles)
markedItems.clear() selectedPositions.clear()
listener?.deleteFiles(files) listener?.deleteFiles(files)
itemCnt = mItems.size
val newItems = SparseArray<View>()
var curIndex = 0
for (i in 0..itemViews.size() - 1) {
if (itemViews[i] != null) {
newItems.put(curIndex, itemViews[i])
curIndex++
}
}
itemViews = newItems
} }
} }
private fun getSelectedMedia(): List<FileDirItem> { private fun getSelectedMedia(): List<FileDirItem> {
val positions = multiSelector.selectedPositions val selectedMedia = ArrayList<FileDirItem>(selectedPositions.size)
val selectedMedia = ArrayList<FileDirItem>(positions.size) selectedPositions.forEach { selectedMedia.add(mItems[it]) }
positions.forEach { selectedMedia.add(mItems[it]) }
return selectedMedia return selectedMedia
} }
@ -198,11 +221,13 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent?.context).inflate(R.layout.list_item, parent, false) val view = LayoutInflater.from(parent?.context).inflate(R.layout.list_item, parent, false)
return ViewHolder(activity, view, itemClick) return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, listener, itemClick)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
views.add(holder.bindView(multiSelectorMode, multiSelector, mItems[position], position)) itemViews.put(position, holder.bindView(mItems[position], fileDrawable, folderDrawable, textColor))
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
} }
override fun onViewRecycled(holder: ViewHolder?) { override fun onViewRecycled(holder: ViewHolder?) {
@ -212,14 +237,15 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
override fun getItemCount() = mItems.size override fun getItemCount() = mItems.size
class ViewHolder(val activity: SimpleActivity, val view: View, val itemClick: (FileDirItem) -> (Unit)) : SwappingHolder(view, MultiSelector()) { class ViewHolder(val view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
fun bindView(multiSelectorCallback: ModalMultiSelectorCallback, multiSelector: MultiSelector, fileDirItem: FileDirItem, pos: Int): View { val multiSelector: MultiSelector, val listener: ItemOperationsListener?, val itemClick: (FileDirItem) -> (Unit)) : SwappingHolder(view, MultiSelector()) {
fun bindView(fileDirItem: FileDirItem, fileDrawable: Drawable, folderDrawable: Drawable, textColor: Int): View {
itemView.apply { itemView.apply {
item_name.text = fileDirItem.name item_name.text = fileDirItem.name
item_name.setTextColor(textColor) item_name.setTextColor(textColor)
item_details.setTextColor(textColor) item_details.setTextColor(textColor)
toggleItemSelection(this, markedItems.contains(pos), pos) // toggleItemSelection(this, selectedPositions.contains(pos), pos)
if (fileDirItem.isDirectory) { if (fileDirItem.isDirectory) {
item_icon.setImageDrawable(folderDrawable) item_icon.setImageDrawable(folderDrawable)
@ -230,17 +256,8 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
item_details.text = fileDirItem.size.formatSize() item_details.text = fileDirItem.size.formatSize()
} }
setOnClickListener { viewClicked(multiSelector, fileDirItem, pos) } setOnClickListener { viewClicked(fileDirItem) }
setOnLongClickListener { setOnLongClickListener { viewLongClicked(); true }
if (!multiSelector.isSelectable) {
activity.startSupportActionMode(multiSelectorCallback)
multiSelector.setSelected(this@ViewHolder, true)
updateTitle(multiSelector.selectedPositions.size)
toggleItemSelection(this, true, pos)
actMode?.invalidate()
}
true
}
} }
return itemView return itemView
@ -251,32 +268,42 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList<FileDir
return activity.resources.getQuantityString(R.plurals.items, children, children) return activity.resources.getQuantityString(R.plurals.items, children, children)
} }
fun viewClicked(multiSelector: MultiSelector, fileDirItem: FileDirItem, pos: Int) { fun viewClicked(fileDirItem: FileDirItem) {
if (multiSelector.isSelectable) { if (multiSelector.isSelectable) {
val isSelected = multiSelector.selectedPositions.contains(layoutPosition) val isSelected = adapterListener.getSelectedPositions().contains(layoutPosition)
multiSelector.setSelected(this, !isSelected) adapterListener.toggleItemSelectionAdapter(!isSelected, layoutPosition)
toggleItemSelection(itemView, !isSelected, pos)
val selectedCnt = multiSelector.selectedPositions.size
if (selectedCnt == 0) {
actMode?.finish()
} else {
updateTitle(selectedCnt)
}
actMode?.invalidate()
} else { } else {
itemClick(fileDirItem) itemClick(fileDirItem)
} }
} }
fun viewLongClicked() {
if (listener != null) {
if (!multiSelector.isSelectable) {
activity.startSupportActionMode(multiSelectorCallback)
adapterListener.toggleItemSelectionAdapter(true, layoutPosition)
}
listener.itemLongClicked(layoutPosition)
}
}
fun stopLoad() { fun stopLoad() {
Glide.clear(view.item_icon) Glide.clear(view.item_icon)
} }
} }
interface MyAdapterListener {
fun toggleItemSelectionAdapter(select: Boolean, position: Int)
fun getSelectedPositions(): HashSet<Int>
}
interface ItemOperationsListener { interface ItemOperationsListener {
fun refreshItems() fun refreshItems()
fun deleteFiles(files: ArrayList<File>) fun deleteFiles(files: ArrayList<File>)
fun itemLongClicked(position: Int)
} }
} }

View File

@ -203,6 +203,10 @@ class ItemsFragment : android.support.v4.app.Fragment(), ItemsAdapter.ItemOperat
return "$type/*" return "$type/*"
} }
override fun refreshItems() {
fillItems()
}
override fun deleteFiles(files: ArrayList<File>) { override fun deleteFiles(files: ArrayList<File>) {
val hasFolder = files.any { it.isDirectory } val hasFolder = files.any { it.isDirectory }
(activity as SimpleActivity).deleteFiles(files, hasFolder) { (activity as SimpleActivity).deleteFiles(files, hasFolder) {
@ -214,8 +218,8 @@ class ItemsFragment : android.support.v4.app.Fragment(), ItemsAdapter.ItemOperat
} }
} }
override fun refreshItems() { override fun itemLongClicked(position: Int) {
fillItems()
} }
interface ItemInteractionListener { interface ItemInteractionListener {