Home > database >  1 button incrementing multiple TextViews
1 button incrementing multiple TextViews

Time:01-04

so my problem may sound a little bit weird but let me explain. I have custom recycle view adapter and custom layout. In custom layout I have buttons which increment or decrement TextView Value. But when I press 1 button it increments like 4 others.

enter image description here enter image description here

As you can see here I only clicked delay and defendant but house and item incremented too. Here's my code

 override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    var pName : TextView = holder.itemView.findViewById(R.id.ingredientName)
    val ingrCount : TextView = holder.itemView.findViewById(R.id.ingredientCount)
    val decrementIngr : Button = holder.itemView.findViewById(R.id.deleteIngeredient)
    val incrementIngr : Button = holder.itemView.findViewById(R.id.addIngredient)


    pName.text = ingredients[position]

    incrementIngr.setOnClickListener{
        val count = Integer.parseInt(ingrCount.text.toString())   1
        ingrCount.text = "$count"
    }
    decrementIngr.setOnClickListener{
        if(Integer.parseInt(ingrCount.text.toString()) - 1 > 0)
        {
            val count = Integer.parseInt(ingrCount.text.toString()) - 1
            ingrCount.text = "$count"
        }
    }

}

CodePudding user response:

The problem is that you are saving your ingrCount state for each item directly on the TextView.text property. Since this is inside a RecyclerView the Views (your custom layouts) get reused (recycled). There are only enough of them created to cover a bit more than the height of your RecyclerView, but as you scroll further the same views are reused. That is why you see your other numbers repeat.

Your click handlers have never incremented or decremented more than a single TextView per click.

Inside override fun onBindViewHolder(holder: ViewHolder, position: Int) you always have to (re)set all parts of the UI that you want to be bound to your underlying data. In your current code you only set the pName.text, this is why that one works correctly. Do the same for the ingrCount.text and it will work as you expect.

You can place a breakpoint or some logging output (log the position parameter for example) inside onBindViewHolder and you will see when different positions are rebound as you scroll up and down the list. This will give you a better understanding on how the RecyclerView works.

EDIT: You need to keep the ingredients count information the same as you do with ingredient names.

How you do it is up to you, you could store (data) classes instead of just ingredient names inside your ingredients Array/ArrayList.

So something like this

class Ingredient(val name: String, var count: Int = 0) {}

Or you could keep the ingredient counts in a separate Array/ArrayList/Map.

Let's say that you would use the class Ingredient to model your data, then your code inside onBindViewHolder would change to

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    var pName : TextView = holder.itemView.findViewById(R.id.ingredientName)
    val ingrCount : TextView = holder.itemView.findViewById(R.id.ingredientCount)
    val decrementIngr : Button = holder.itemView.findViewById(R.id.deleteIngeredient)
    val incrementIngr : Button = holder.itemView.findViewById(R.id.addIngredient)

    val ingredient = ingredients[position] 
    pName.text = ingredient.name
    ingrCount.text = ingredient.count.toString()

    incrementIngr.setOnClickListener{
        ingredient.count  = 1
        ingrCount.text = ingredient.count.toString()
    }
    decrementIngr.setOnClickListener{
        if(ingredient.count > 0)
        {
            ingredient.count -= 1
            ingrCount.text = ingredient.count.toString()
        }
    }
}
  •  Tags:  
  • Related