Last active
July 10, 2023 09:24
-
-
Save Miha-x64/3248e4b08ec31094ed65e00565aa8ff3 to your computer and use it in GitHub Desktop.
Another approach to EditTexts inside RecyclerView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.text.Editable | |
import android.text.SpannableStringBuilder | |
import android.view.ViewGroup | |
import android.view.ViewGroup.LayoutParams.MATCH_PARENT | |
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT | |
import android.widget.EditText | |
import androidx.recyclerview.widget.DiffUtil | |
import androidx.recyclerview.widget.RecyclerView | |
/** | |
* Another approach to EditTexts inside RecyclerView. | |
* @author Mike Gorünóv | |
*/ | |
class EditableAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | |
private val editables = ArrayList<Editable?>() | |
private var strings = emptyList<String>() | |
@Suppress("SetterBackingFieldAssignment") | |
var items: List<String> = | |
object : AbstractList<String>() { | |
override val size: Int get() = strings.size | |
override fun get(index: Int): String = editables.getOrNull(index)?.toString() ?: strings[index] | |
} | |
set(value) { | |
DiffUtil.calculateDiff(object : DiffUtil.Callback() { | |
override fun getOldListSize(): Int = strings.size | |
override fun getNewListSize(): Int = value.size | |
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = | |
(editables.getOrNull(oldItemPosition) ?: strings[oldItemPosition]) | |
.contentEquals(value[newItemPosition]) | |
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = | |
areItemsTheSame(oldItemPosition, newItemPosition) | |
}).dispatchUpdatesTo(this) | |
editables.clear() | |
strings = value | |
notifyItemRangeChanged(0, strings.size, Unit) // drop and recreate editables for bound views | |
} | |
override fun getItemCount(): Int = | |
strings.size | |
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = | |
object : RecyclerView.ViewHolder(EditText(parent.context).apply { | |
layoutParams = RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT) | |
setEditableFactory(IdentityEditableFactory) | |
}) {} | |
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | |
(holder.itemView as EditText).text = editables.getOrNull(position) | |
?: SpannableStringBuilder(strings[position]).also { | |
while (editables.lastIndex < position) editables.add(null) | |
editables[position] = it | |
} | |
} | |
private object IdentityEditableFactory : Editable.Factory() { | |
override fun newEditable(source: CharSequence): Editable = source as Editable | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment