简体   繁体   中英

How to change the background color of selected item in RecyclerView

I created a Kotlin mobile app. In my app i use the RecyclerView with adapter. I want to changing the background color of item clicked in my RecyclerView , and when i click on another item, the color will be change and the color of the first item clicked return to the default color.

override fun onBindViewHolder(holder: ViewHolder, position: Int) { 
       val itemCategory: ProductCategoryData = categories[position] 
       holder.categoryId.text = itemCategory.id.toString() 

       println(holder.categoryId.text) 
       println(itemCategory.name?.get("En").toString()) 
       holder.categoryName.text = itemCategory.name?.get("En").toString() 
      ............ 
       holder.itemView.setOnClickListener { 
           rowindex = position 
           mListener?.onItemClick(holder.itemView, categories[position]) 
       } 
       if (rowindex == position) { 
           holder.itemView.setBackgroundColor(Color.parseColor("#FED07A")) 
       } else { 
           holder.itemView.setBackgroundColor(Color.parseColor("#ffffff")) 
       } 

   }

What should i change in my code to make it functional

To change the background of a clicked item in the RecyclerView you need to catch the click in the adapter using an iterface:

interface ItemClickListener {
    fun onItemClickListener(item: Item, position: Int)
}

When we click we will get the item and the items position. In our bind function in the adapter we will set the on click listener:

container.setOnClickListener {
    onClickListener.onItemClickListener(item, position)
}

In your activity you will then implement this interface:

class MainActivity : AppCompatActivity(), ItemAdapter.ItemClickListener {

Next we need to implement the background changing logic on item click. The logic is this: when the user clicks on an item, we check if the background on the clicked item is white (the item is not previously clicked) and if this condition is true, we change the background on all of the items in the RecyclerView to white (to invalidate previously clicked and marked items if there are any) and then change the background color of the clicked item to teal to mark it. And if the background of the clicked item is teal (which means the user clicks again on the same previously marked item), we change the background color on all of the items to white. First we will need to get our item background color as a ColorDrawable. We will use an iterator function to go through all of the items (children) of the RecyclerView and forEach() function to change the background on everyone of them. This method will look like this:

 override fun onItemClickListener(item: Item, position: Int) {
        val itemBackground: ColorDrawable =
            binding.recycler[position].background as ColorDrawable
        if (itemBackground.color == ContextCompat.getColor(this, R.color.white)) {
            binding.recycler.children.iterator().forEach { item ->
                item.setBackgroundColor(
                    ContextCompat.getColor(
                        this,
                        R.color.white
                    )
                )
            }
            binding.recycler[position].setBackgroundColor(
                ContextCompat.getColor(this, R.color.teal_200)
            )
        } else {
            binding.recycler.children.iterator().forEach { item ->
                item.setBackgroundColor(
                    ContextCompat.getColor(
                        this,
                        R.color.white
                    )
                )
            }
        }
    }

So now you change the background on item click, if you click the same item, you will change the background back to what it was before.

Call notifyDataSetChanged

holder.itemView.setOnClickListener { 
   rowindex = position 
   mListener?.onItemClick(holder.itemView, categories[position])
   notifyDataSetChanged()          
} 

if (rowindex == position) {            
    holder.itemView.setBackgroundColor(Color.parseColor("#FED07A")) 
} else { 
    holder.itemView.setBackgroundColor(Color.parseColor("#ffffff")) 
}  

Most of the answers for such a question, are about to Override Onclick in onBindViewHolder or implementing an interface for clicking in recycler view. But as we all know, onBindViewHolder is called as your views are populated during scrolling. Thus, you will have numerous calls to setOnClickListener so it is not an efficient way and also implementing interface is not as easy as the answer I got.

Here is how you can access selecting items in recycler view and change its background or do what ever you want when an item is selected.

In your ViewHolder constructor use setOnTouchListener for itemView (the argument of constructor) in this way.

    itemView.setOnTouchListener((v, event) -> {

                if (event.getAction() == MotionEvent.ACTION_UP) {

                    if (v.getTag() == null) {
                        v.setTag(true);
                        v.setBackgroundColor(Color.parseColor("#F31807"));
                    } else {
                        v.setBackgroundColor(Color.TRANSPARENT);
                        v.setTag(null);
                    }
                }

                if (event.getAction() == MotionEvent.ACTION_MOVE) {
                   //default color
                    v.setBackgroundColor(Color.TRANSPARENT);
                }
                return true;
            });

We use ACTION_UP for check if user pressed the item and after that we save a boolean in view's flag so that we can press every items how many times we want and see the color is changing. ACTION_MOVE if block is for prevent selecting items when scrolling the recycler view. If you see that selecting one item is affecting another items selection, you can use this answer:

issue : RecyclerView messed up data when scrolling

In the end, if you are curious about why we return true in method see this video to understand.

tutorial on OnTouchListener And Motionevent

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM