0

I've created an app that has a list of cards within a RecyclerView that each have functionality of their own. I wanted to have each card choose the next color from an array defined in my colors.xml. In order to accomplish this, within my ViewHolder initialization, I set the background color of the card using cardContainer.setBackgroundColor(colors[this.layoutPosition % colors.size]. This would make it so that the colors would be cycled when more cards are created. However, I seem to be encountering the issue where my layout position is negative despite there being a set number of cards (25) created at the beginning.

While trying to search around and find the cause, I read here that if you call notifyDataSetChanged() the adapterPosition will become -1. While I am not using adapterPosition here, I thought that maybe it would be a similar issue, however, I am not adding any additional data at the time of the creation of the list items.


My ViewHolder code can be seen below. This is where the issue arises, but if any additional code is necessary feel free to ask.

    class ViewHolder(itemView : View, private val listener: HabitClickListener) : RecyclerView.ViewHolder(itemView) {
        val habitTitle: TextView = itemView.habitTitle
        val streak: TextView = itemView.dayCounter
        val cardContainer: LinearLayout = itemView.cardContainer

        private val decreaseCounterButton : Button = itemView.decreaseCounterButton
        private val increaseCounterButton : Button = itemView.increaseCounterButton

        init {
            chooseCardColor() // Choose the color for each card from the available colors
            itemView.setOnClickListener {
                listener.onCardClick(this.layoutPosition)
            }
            decreaseCounterButton.setOnClickListener {
                listener.onDecrease(this.layoutPosition)
            }
            increaseCounterButton.setOnClickListener {
                listener.onIncrease(this.layoutPosition)
            }
        }

        private fun chooseCardColor() {
            val colors = itemView.resources.getIntArray(R.array.cardColors)
            cardContainer.setBackgroundColor(colors[this.layoutPosition % colors.size])
        }
    }
DeveloperRyan
  • 837
  • 2
  • 9
  • 22
  • As I read more about the method `getLayoutPosition` I suspect it might be different than what I initially thought. I thought it was the same as the `onBindViewHolder` `position`, is this not the case? – DeveloperRyan Jun 01 '20 at 05:10

1 Answers1

2

I will try to simplify this further, you should use the getAdapterPosition of ViewHolder

In recyclerview, storing the data and displaying the data are two separate things(Notice how you can use different managers(LinearLayoutManager, GridLayoutManager) to present the data in a different way.When some data changes in recyclerview, it notifies the ui to change what is shown in the screen. Even though it is really small, there is a delay between the change in the content of recyclerview and change in layout, that's why these two behave differently.

My information in this may be outdated but also don't just use the position variable as it can be inconsistent when another element is added/deleted to recyclerview due to how onBindViewHolder()(existing variables position wasn't updated when a new element is added/deleted) behaves. Instead use getAdapterPosition().

Edit: Quick fix if you don't want to deal with viewHolder gimmicks.

Add a new field to your custom object which decides what color it should be. Then make this calculation in your fragment/activity by looking at the index of your object in the list instead of doing the calculation in the viewHolder. Now you can set the color you want inside the viewHolderby looking at your object's new field. Of course you should be careful when adding/deleting a new object when you do this, but same holds true when you do it via viewHolder

Prethia
  • 1,183
  • 3
  • 11
  • 26
  • Thank you for this explanation, that helps clear up some of the confusion between the two! It seems like when I switch to adapterPosition, the exact same bug still persists though. – DeveloperRyan Jun 01 '20 at 05:36