Мне нужна помощь в реализации 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)
    }
}

Это всего лишь базовый набросок того, что вы можете сделать, но я надеюсь, что вы уловили идею. Относитесь к адаптеру как к собственному, независимому классу, который управляет своим собственным состоянием и логикой, и позволяйте другим компонентам взаимодействовать с ним в ограниченном режиме, предоставляя ему только те данные и события, которые ему нужны.

Другие вопросы по тегам