Change color of un/selected Items in RecyclerView

Viewed 48

My problem is that I want to select an item in a RecyclerView and it should change the color and if I click on another the first selected item should change to the default color (and the last clicked should have the selected color).

I have already a color change of the selected one and if I click on the selected one again it changes to default color. Now I am only missing that if I click on an unselected item and if I have already a selected item they "switch" the color

This is my SubItem class:

class SubItem(val channel: Channel) : Item<GroupieViewHolder>() {
    @SuppressLint("ResourceAsColor")
    override fun bind(viewHolder: GroupieViewHolder, position: Int) {

        val profileImageUrl =  channel.channel_logo

        viewHolder.itemView.sub_item_name.text = channel.channel_name

        viewHolder.itemView.sub_item_layout.setBackgroundResource(R.color.white)
        viewHolder.itemView.sub_item_name.setTextColor(R.color.colorSecondaryText)

        val targetImageView = viewHolder.itemView.sub_item_profile
        try {
            Picasso.get().load(profileImageUrl)
                .placeholder(R.drawable.ic_baseline_account_circle_24)
                .into(targetImageView)
        }catch (e:Exception){
            Log.d("SubItem","${e.message}")
        }

        viewHolder.itemView.sub_item_layout.setOnClickListener {
            if (selected_position == position){
                selected_position = null
                viewHolder.itemView.sub_item_layout.setBackgroundResource(R.color.white)
                viewHolder.itemView.sub_item_name.setTextColor(R.color.colorSecondaryText)
            }
            else{
                selected_position = position
                viewHolder.itemView.sub_item_layout.setBackgroundResource(R.color.colorSecondaryText)
                viewHolder.itemView.sub_item_name.setTextColor(R.color.black)
            }
        }
    }

    override fun getLayout(): Int {
        return R.layout.subscription_item
    }
}

If it is helping here is my function where I add the items to the RecyclerView

private fun fetchSubs() {
        val uid = auth.uid
        val user = database.getReference("/users/$uid/subscriptions")
        val adapter = GroupAdapter<GroupieViewHolder>()

        user.addListenerForSingleValueEvent(object : ValueEventListener{
            @SuppressLint("NotifyDataSetChanged")
            override fun onDataChange(p0: DataSnapshot) {
                p0.children.forEach{
                    val sub = it.getValue(Subscription::class.java) ?: return
                    if (sub.subscribed == true) {
                        val ref = database.getReference("/channels/${sub.channel_uid}")
                        ref.addListenerForSingleValueEvent(object : ValueEventListener {
                            override fun onDataChange(p0: DataSnapshot) {
                                val channel = p0.getValue(Channel::class.java) ?: return

                                adapter.add(SubItem(channel))
                            }
                            override fun onCancelled(error: DatabaseError) {

                            }
                        })
                    }
                }

                adapter.setOnItemClickListener{ item, view ->
                    val subItem = item as SubItem
                    val channelName = subItem.channel.channel_name
                    val channelUid = subItem.channel.uid

                    Toast.makeText(requireContext(),"$channelName : $channelUid", Toast.LENGTH_SHORT).show()

                    fetchSubs()
                }

                sub_recyclerview.adapter = adapter
            }
            override fun onCancelled(error: DatabaseError) {

            }
        })
    }

sorry that I am not using Models and Adapter

1 Answers

For everyone who uses groupie like me this could help you in future.

This is my solution for my Problem.

SubItem class

class SubItem(val channel: Channel) : Item<GroupieViewHolder>() {
    @SuppressLint("ResourceAsColor")
    override fun bind(viewHolder: GroupieViewHolder, position: Int) {
        val profileImageUrl =  channel.channel_logo

        viewHolder.itemView.sub_item_name.text = channel.channel_name

        val targetImageView = viewHolder.itemView.sub_item_profile

        try {
            Picasso.get().load(profileImageUrl)
                .placeholder(R.drawable.ic_baseline_account_circle_24)
                .into(targetImageView)
        }catch (e:Exception){
            Log.d("SubItem","${e.message}")
//            Toast.makeText(,e.message,Toast.LENGTH_SHORT).show()
        }

        checkFilter(viewHolder,position)
    }

    @SuppressLint("ResourceAsColor")
    private fun checkFilter(v: GroupieViewHolder, p: Int) {
        when (SubscriptionsFragment.list[p]) {
            true -> {
                v.itemView.sub_item_layout.setBackgroundResource(R.color.colorDivider)
                v.itemView.sub_item_name.setTextColor(R.color.black)
            }
            false -> {
                v.itemView.sub_item_layout.setBackgroundResource(R.color.white)
                v.itemView.sub_item_name.setTextColor(R.color.colorSecondaryText)
            }
        }
    }

    override fun getLayout(): Int {
        return R.layout.subscription_item
    }
}

My function with setOnItemClickListener

private fun fetchSubs() {
        val uid = auth.uid
        val user = database.getReference("/users/$uid/subscriptions")
        val adapter = GroupAdapter<GroupieViewHolder>()

        user.addListenerForSingleValueEvent(object : ValueEventListener{
            @SuppressLint("NotifyDataSetChanged")
            override fun onDataChange(p0: DataSnapshot) {
                list = mutableListOf()
                p0.children.forEach{
                    val sub = it.getValue(Subscription::class.java) ?: return
                    if (sub.subscribed == true) {
                        val ref = database.getReference("/channels/${sub.channel_uid}")
                        ref.addListenerForSingleValueEvent(object : ValueEventListener {
                            override fun onDataChange(p0: DataSnapshot) {
                                val channel = p0.getValue(Channel::class.java) ?: return

                                list.add(false) // created in companion object: var list =  mutableListOf<Boolean>()
                                oldList.add(false) // created in companion object: var oldlist =  mutableListOf<Boolean>()
                                adapter.add(SubItem(channel))
                            }
                            override fun onCancelled(error: DatabaseError) {

                            }
                        })
                    }
                }

                adapter.setOnItemClickListener{ item, view ->
                    val subItem = item as SubItem
                    val pos = adapter.getAdapterPosition(subItem)


                    // Here happens the magic
                    list[pos] = !list[pos] // change selected item from false to true or from true to false
                    val l = list[pos] // saving Boolean

                    list = mutableListOf()
                    oldList.forEach{ // using oldList to loop so many times I need
                        list.add(false) // setting all to false
                    }
                    if (l){ // if Boolean is true
                        list[pos] = !list[pos] // change selected item from false to true
                    }


                    val channelUid = subItem.channel.uid

                    fetchVideos(channelUid)
                    adapter.notifyDataSetChanged() // refresh all items in SubItem
                }

                try {
                    sub_recyclerview.adapter = adapter
                } catch(e:Exception){
                    Log.d("fetchSubs","${e.message}")
                }
            }
            override fun onCancelled(error: DatabaseError) {

            }
        })
    }
Related