#android #kotlin #android-recyclerview #android-adapter #notifydatasetchanged
Вопрос:
Я пытаюсь реализовать recyclerview, в котором есть список элементов 50-100. Каждая строка содержит представление TextView и представление Edittext. Пользователь вводит комментарии к каждой строке, содержащей редактируемый текст. Но проблема в том, что когда пользователь вводит значение и пытается прокрутить его вверх/вниз, данные, введенные в строку, теряются.
Затем я попробовал другое решение. Я обновляю значение массива в этой позиции и уведомляю об изменении, оно выводит значение во всех строках, содержащих редактируемый текст
Мой Адаптер:
class MyAdapter(
val context: Context,
val itemList: MutableList<String>
) :
RecyclerView.Adapter<MyAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var txtLabel: TextView = view.findViewById(R.id.txtLabel)
var etValue: EditText = view.findViewById(R.id.etValue)
var watcher: TextWatcher? = null
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.list_comment, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.txtLabel.text = itemList[position]
holder.watcher = holder.etValue.doAfterTextChanged { text ->
try {
updateItem(
position,
text.toString()
)
} catch (ex: Exception) {
println(ex.message)
}
}
}
override fun getItemCount(): Int {
return itemList.size
}
fun updateItem(position: Int, item: String) {
itemList.add(position, item)
notifyDataSetChanged()
}
}
При запуске метода updateItem он обновляет все строки, но я передаю позицию только для обновления в этой позиции. Пожалуйста, объясните, в чем проблема.
Комментарии:
1. В
updateItem
: Я думаю , вы имели в видуitemList.set(position, item)
, что нетitemList.add(position, item)
.notifyDataSetChanged()
кажется, в этом нет необходимости.2. add сделает то же самое, если мы передадим индекс вместе с ним. Это добавляет ценность при заданном индексе
3. Но таким образом вы создаете все больше и больше предметов в своем переработчике. Ты это имеешь в виду? Каждый раз, когда вы вставляете символ в редактируемый текст, вы добавляете новый элемент в recyler со значением текущего редактируемого текста.
4. Да, ваша точка зрения справедлива. Но это также меняет цвет представления текста, в котором пользователь ввел ввод. В этом случае я должен уведомить об этом()
5. Вы можете использовать
etValue.onFocusChangeListener
для изменения цвета TexView. (В каждый момент времени есть только один сфокусированный взгляд)
Ответ №1:
holder.etValue.doAfterTextChanged
добавлю а TextChangedListener
. Вы не удаляете его позже, и, таким образом, вы получаете несколько прослушивателей, прикрепленных к одному редактируемому тексту.
Вы могли бы переписать свой код следующим образом:
class MyAdapter(
val context: Context,
val itemList: MutableList<String>
) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
lateinit var onTextUpdated: (String) -> Unit
var txtLabel: TextView = view.findViewById(R.id.txtLabel)
var etValue: EditText = view.findViewById(R.id.etValue)
init { // TextChanged listener added only once.
etValue.doAfterTextChanged { editable ->
val text = editable.toString()
onTextUpdated(text)
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.list_comment, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.txtLabel.text = itemList[position]
holder.onTextUpdated = { text -> // each time holder is bound, new listener will be assigned
try {
updateItem(
position,
text
) // update cached value
holder.txtLabel.text = text // update label
} catch (ex: Exception) {
println(ex.message)
}
}
}
override fun getItemCount(): Int {
return itemList.size
}
fun updateItem(position: Int, item: String) {
itemList[position] = item
// this might mess up the EditTexts focus.
// notifyDataSetChanged()
}
}
Комментарии:
1. Это дает мне ошибку onTextUpdated, которая не была инициализирована
2. Должно быть, вы неправильно его изменили.
onTextUpdated
свойство должно быть установлено перед доступом к нему.3. Да, я это сделал. Спасибо за помощь, братан