После обновления recyclerview слетает цвет у выбраного item
Пишу приложение ToDo List. Все таски реализованы в виде элементов RecyclerView. Пользователь через контекстное меню может выбирать цвет для определенного таска. Обновление RecyclerView произвожу с помощью SwipeRefreshLayout, после которого цвет выбранного таска исчезает. Сами цвета хранятся в SharedPreferences.
Код TaskViewHolder:
inner class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener, PopupMenu.OnMenuItemClickListener {
private val taskDescription: TextView = itemView.taskDescription
private val cardView: CardView = itemView.task_list_item
private var checkedItem: Int = -1
init {
cardView.setOnClickListener(this)
}
fun bind(description: String) {
taskDescription.text = description
}
fun bindColorToView(position: Int) {
if (checkedItem == position) {
val colorPreferences =
context.getSharedPreferences("Color Settings", Context.MODE_PRIVATE)
cardView.setCardBackgroundColor(colorPreferences.getInt("Color code", Color.WHITE))
}
}
override fun onClick(view: View?) {
showPopupMenu(view)
}
private fun showPopupMenu(view: View?) {
val popupMenu = PopupMenu(view?.context, view)
popupMenu.inflate(R.menu.context_menu)
popupMenu.setOnMenuItemClickListener(this)
popupMenu.show()
}
override fun onMenuItemClick(menuItem: MenuItem?): Boolean {
return when (menuItem?.itemId) {
R.id.importance_Low -> {
cardView.setCardBackgroundColor(Color.GREEN)
val colorPreference =
context.getSharedPreferences("Color Settings", Context.MODE_PRIVATE)
colorPreference.edit().putInt("Color code", Color.GREEN).apply()
true
}
R.id.importance_Medium -> {
cardView.setCardBackgroundColor(Color.YELLOW)
val colorPreference =
context.getSharedPreferences("Color Settings", Context.MODE_PRIVATE)
colorPreference.edit().putInt("Color code", Color.YELLOW).apply()
true
}
R.id.importance_High -> {
cardView.setCardBackgroundColor(Color.RED)
val colorPreference =
context.getSharedPreferences("Color Settings", Context.MODE_PRIVATE)
colorPreference.edit().putInt("Color code", Color.RED).apply()
true
}
else -> false
}
}
}
onBindViewHolder метод:
override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
content[position].description?.let { holder.bind(it) }
holder.bindColorToView(position)
}
Метод обновления RecyclerView:
private fun refreshData() {
refresher.isRefreshing = true
contentViewModel.getTaskList(applicationContext)
contentViewModel.tasks.observe(this, Observer {
contentAdapter = TaskAdapter(it, applicationContext)
taskList.adapter = contentAdapter
contentAdapter.notifyDataSetChanged()
})
refresher.isRefreshing = false
}
Ответы (2 шт):
Я не вижу в вашем коде где вы меняете значние
checkedItem. Смею предположить, что проблема в том, что после апдейта вашегоAdapter-аэто значние теряется.Еще проблема может крыться здесь:
fun bindColorToView(position: Int) { if (checkedItem == position) { val colorPreferences = context.getSharedPreferences("Color Settings", Context.MODE_PRIVATE) cardView.setCardBackgroundColor(colorPreferences.getInt("Color code", Color.WHITE)) } }RecyclerViewреализует паттернViewHolder, а значит, что он переиспользуетView. Поэтому дляRecyclerView.Adapterесть негласное правило: "Если вViewHolder-еесть.ifто должен быть иelseт.к. вы можете получить баг когда придет переиспользованнаяViewона не попадет поifи там останется прошлое значние.А вообще как это делается по хорошему: В
Presenter/ViewModelгенерится список с готовыми моделями, любые изменения (в том числе и цвет) должны изменяться в этом списке. А потом простоAdapterдолжен заполниться нужными значениями.
Решение: Я сохранил в SharedPreferences позицию RecyclerView Item что дало в дальнейшем возможность обновлять сам RecyclerView с сохранением цвета у вібраного таска