0

I expect my 'heart' icon to change when my ViewHolder item is clicked. Fortunately, it does this. However, an issue arises as multiple items seems to replicate the button click.

What I mean is: If I tap the heart on item number 1. Other items throughout the list replicate also change the heart. Why is this happening and what is a potential fix? I am confused why this issue is occuring as I am referencing the ViewHolder item. Thus, shouldn't it only affect the item I am clicking?

View Holder

        fun bind(item: Location) {
            heart.setOnClickListener {
                item.fav = item.fav != true
                heart.setImageDrawable(
                when (item.fav) {
                    false -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_border_heart))
                    else -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_whole_heart))
                })

            }
        }
PandaPlaysAll
  • 927
  • 2
  • 9
  • 15

3 Answers3

1

You didn't check the view ID in the onClick method. You can set onClick directly on the views as below.

    class LocationViewHolder(v: View): RecyclerView.ViewHolder(v), View.OnClickListener {

private val actLoc: TextView = v.findViewById(R.id.location_main)
private val genLoc: TextView = v.findViewById(R.id.location_subtitle)
private val heart: ImageView = v.findViewById(R.id.heart)
private lateinit var item: Location

fun bind(item: Location) {
    this.item = item
    actLoc.setText(item.actualLocation)
    actLoc.setOnClickListener {
        Toast.makeText(itemView.context, "${item.cords}", Toast.LENGTH_SHORT).show()
    }
    genLoc.setText(item.genLocation)
    genLoc.setOnClickListener {
        Toast.makeText(itemView.context, "${item.cords}", Toast.LENGTH_SHORT).show()
    }
    heart.setOnClickListener {
        item.fav = item.fav != true
        heart.setImageDrawable(
            when (item.fav) {
                false -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_border_heart))
                else -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_whole_heart))
            })

    }
}
1

onBindViewHolder you need to save list of fave in change item image base on that list otherwise it changes randomly as view recreates

     fun bind(item: Location) {

 heart.setImageDrawable(
                when (item.fav) {
                    false -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_border_heart))
                    else -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_whole_heart))
                })
            heart.setOnClickListener {
                item.fav = item.fav != true
                heart.setImageDrawable(
                when (item.fav) {
                    false -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_border_heart))
                    else -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_whole_heart))
                })

            }
        }
umar ali Khan
  • 28
  • 1
  • 5
0

However, an issue arises as multiple items seems to replicate the button click.

it is because of the cell recycling mechanism

heart.setImageDrawable(
   when (item.fav) {
       false -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_border_heart))
       else -> (ContextCompat.getDrawable(itemView.context, R.drawable.ic_whole_heart))
})

should be part of the bind function in the viewholder and not part of the onClick function. What I would expect is

  • Click informs the viewmodel
  • Viewmodel update the dataset
  • Viewmodel informs the recyclerview
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • That was one of my thought patterns. However, I decided to scrap that idea as I had the ViewModel tied to the Adapter. Therefore, I wasn't able to access the ViewModel from the ViewHolder. How would you allow connecting the ViewModel with other aspects of the recyclerview? – PandaPlaysAll Sep 15 '20 at 07:49
  • you could pass a lambda to the constructor of your adapter to enable the adapter -> activity -> viewmodel communication. – Blackbelt Sep 15 '20 at 07:51