Мне нужна помощь в реализации notifyItemChanged для моего recyclerview
Я пытаюсь установить цвет фона для 1 элемента в моем recyclerview, когда я нажимаю кнопку. Я получаю индекс конкретного элемента и пытаюсь использовать функцию, которая включает notifyItemChange в методе onclick моей кнопки в Activity. Но он продолжает менять цвет первого элемента в recyclerview, даже если я жестко запрограммировал номер индекса в функцию. Я знаю, что получаю правильный индекс выбранного элемента, но что-то упускаю. Возможно, какой-то код в адаптере? Я не могу получить достаточно информации из других ответов, чтобы понять, как это сделать. Любая помощь? Спасибо!
Переменная для selectedPosition в Activity:
private var newSelectedPosition: Int = 0
Кнопка onClick в действии:
R.id.btn_add_daily_report_submit -> {
Log.e("tag", "$newSelectedPosition")
updateSingleItem(newSelectedPosition)
}
Функция updateSingleItem() в Activity:
private fun updateSingleItem(index: Int) {
Log.e("updateSingleItem", "$newSelectedPosition")
card_view.setBackgroundColor(resources.getColor(R.color.green))
adapter.notifyItemChanged(index)
}
setOnClickListener из интерфейса адаптера для записи индекса выбранного элемента в Activity:
adapter.setOnClickListener(object :
DailyReportsAdapter.OnClickListener {
override fun onClick(position: Int, user: User) {
newSelectedPosition = position
Log.e("tag", "$newSelectedPosition")
et_daily_report_employee.text = getString(
R.string.tv_name,
user.firstName,
user.lastName
)
}
})
Класс адаптера:
open class DailyReportsAdapter(
private val context: Context,
private var list: ArrayList<User>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// A global variable for OnClickListener interface.
private var onClickListener: OnClickListener? = null
private var selectedItemPosition: Int = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_daily_report_layout,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, @SuppressLint("RecyclerView") position: Int) {
val model = list[position]
if (holder is MyViewHolder) {
holder.itemView.employee_name.text = "${model.firstName} ${model.lastName}"
j
// Назначаем событие клика для просмотра элемента и передаем необходимые параметры в функцию клика. holder.itemView.setOnClickListener { if (onClickListener != null) {onClickListener!!.onClick(позиция, модель) } } } }
override fun getItemCount(): Int {
return list.size
}
fun setOnClickListener(onClickListener: OnClickListener) {
this.onClickListener = onClickListener
}
/**
* An interface for onclick items.
*/
interface OnClickListener {
fun onClick(position: Int, user: User)
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
1 ответ
Вам нужно отделить (вещь, которая принимает данные и управляет их отображением) от остальной части пользовательского интерфейса (например, его хостинга). Если в вашем пользовательском интерфейсе есть кнопка, которая означает «обновить что-то в адаптере», на самом деле все или
Fragment
должен сказать адаптеру: «Эй, вот что, делай то, что тебе нужно».
Это не обязательное требование , но такое разделение проблем означает, что адаптер может быть самодостаточным, и вещи, которые взаимодействуют с адаптером, не должны знать, как он работает, не нужно ковыряться в нем внутри (например, вызов
notifyItemChanged
) или что-то в этом роде. Объявив видимые (не частные) методы адаптера, вы можете определить его интерфейс и то, как другие компоненты должны взаимодействовать с ним. Затем вы можете обрабатывать всю логику того, как это должно работать внутри метода и самого адаптера.
Поэтому я не знаю, как работает ваше приложение, но это всего лишь пример, чтобы вы могли найти способ адаптировать его для того, что вам действительно нужно. Я представлю, что у вас есть список с элементами, которые вы можете выбрать, нажав на них, но в действии есть кнопка, которую нужно нажать, чтобы фактически выделить последний нажатый элемент.
в
Activity
,
onCreate
или что-то еще
button.setOnClickListener {
adapter.highlightLastTapped()
}
в
Adapter
// making this nullable for a "nothing selected" value, and it's easy to work with
// using Kotlin's null-checking features
private var lastTappedPosition: Int? = null
// check this in ``onBindViewHolder`` to see if that item should be highlighted
private var currentlyHighlightedPosition: Int? = null
// internal function you can call from a click listener on an item
private fun setLastTappedPosition(position: Int) {
lastTappedPosition = position
// If something was previously highlighted, we can update it right here.
// This is an example of the kind of logic you can do if you put the adapter
// in charge of its own state, instead of calling notifyItemChanged etc from outside
val previousHighlight = currentlyHighlightedPosition
currentlyHighlightedPosition = null
previousHighlight?.let {
notifyItemChanged(it)
}
}
// externally visible function - this is just "highlight whatever you need to"
// but you could pass in a parameter if you want. Keep the logic in the adapter though!
fun highlightLastTapped() {
lastTappedPosition?.let {
currentlyHighlightedPosition = it
notifyItemChanged(it)
}
}
Это всего лишь базовый набросок того, что вы можете сделать, но я надеюсь, что вы уловили идею. Относитесь к адаптеру как к собственному, независимому классу, который управляет своим собственным состоянием и логикой, и позволяйте другим компонентам взаимодействовать с ним в ограниченном режиме, предоставляя ему только те данные и события, которые ему нужны.