Inside a RecyclerView : how to keep a Favourite ImageButton switched On? (now it switches off in half a second)

Viewed 12

I have 2 buttons inside a holder inside a recyclerview: Red Button and Black Button Ideally, I would like the Red favourite button to remain VISIBLE inside RecyclerView for each item I saved to Favourites - and black for normal items. The default button should appear black.

Everything works (saving into DAO the right items, and the button turns red on click but only for a split second). In the init block, I pass an onClickListener to connect the Button with the logic in the Fragment (saving).

The logic implemented in onBindViewHolder worked ok in changing the colours and keeping them, but I couldn't pass it to the fragment (I kept especially this part - commented out) - and it interfered with the onclickListener written in the SlidingItemViewHolder when I decided to keep them both.

Any help is ok, I read the official documentation, tried replacing it with Button.setDrawable, and tried multiple variations, it's like finding a needle in a haystack! How to keep the Favourite button pressed?

Sliding Item Adapter


import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.example.R
import com.example.databinding.SlidingItemBinding

/**
 * [SlidingItemAdapter]  feeds the data to the manual Sliders. It implements the click changes of the red/bleack heart
 * We create a clicklistener that can be called from any fragment or activity
 */

class SlidingItemAdapter(private val imgList: List<Int>, private val manualQuoteList: List<String>, private val listener: draOnItemClickListener) :
    RecyclerView.Adapter<SlidingItemAdapter.SlidingItemViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SlidingItemViewHolder {
        val binding = SlidingItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return SlidingItemViewHolder(binding)
    }

    override fun onBindViewHolder(holder: SlidingItemViewHolder, position: Int) {
        // we take a random quote and a random image

        holder.binding.imageViewManual.setImageResource(imgList[position])
        holder.binding.quoteManual.setText(manualQuoteList[position])

        // setting this view gone here - 
        holder.binding.heartRedFavouriteButton.setVisibility(View.GONE)
        holder.binding.heartFavouriteButton.setVisibility(View.VISIBLE)

//    //  changing the colours - adding to the database moved in the fragment
//    holder.binding.heartFavouriteButton.setOnClickListener {
//        if (holder.binding.heartRedFavouriteButton.isGone) {
//            println("dra s-a dat click pe negru in adapter")
//            holder.binding.heartFavouriteButton.setVisibility(View.GONE)
//            holder.binding.heartRedFavouriteButton.setVisibility(View.VISIBLE)
//        }
//    }
//
//    // just changing the colours of the buttons
//    holder.binding.heartRedFavouriteButton.setOnClickListener {
//        if (holder.binding.heartFavouriteButton.isGone) {
//
//            println("dra s-a dat click pe rosu in adapter")
//            holder.binding.heartFavouriteButton.setVisibility(View.VISIBLE)
//            holder.binding.heartRedFavouriteButton.setVisibility(View.GONE)
//        }
//    }
    }

    // making it an inner class we manage to get the listener defined at the beginning
    inner class SlidingItemViewHolder(val binding: SlidingItemBinding):
        RecyclerView.ViewHolder(binding.root), View.OnClickListener {

            val imageView: ImageView = binding.imageViewManual
            val textView: TextView = binding.quoteManual
            val blackHeart: ImageButton = binding.heartFavouriteButton
            val redHeart: ImageButton = binding.heartRedFavouriteButton

        // similar with constructor method in java- This listener is taken by the draOnItemClickListener
        // and then you can process it in the Fragment where it gets the exact position you need.

            init {
                blackHeart.setOnClickListener(this)
//                redHeart.setOnClickListener(this)
//                imageView.setOnClickListener(this)
            }

        override fun onClick(v: View?) {
            val position = adapterPosition

            if (position != RecyclerView.NO_POSITION) {
                listener.draOnItemClick(position) }

            if (blackHeart.isVisible) {
                println("dra s-a dat click pe negru")
                redHeart.setVisibility(View.VISIBLE)
                blackHeart.setVisibility(View.GONE)

            }

//            if (redHeart.isVisible) {
//                println("dra s-a dat click pe rosu")
//                blackHeart.setVisibility(View.VISIBLE)
//                redHeart.setVisibility(View.GONE)
//                return
//            }
            }
        }

    override fun getItemCount(): Int {
        return imgList.size
    }

    interface draOnItemClickListener {
        fun draOnItemClick(position: Int)
    }

}

Fragment



    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
      
        bindingManual.lifecycleOwner = viewLifecycleOwner

        // getting the lists here bc at the beginning the Fragment is not initialized yed
        imgList = context?.let { viewModel.getThemAll(it) }?.toList()!!
        val manualQuoteList: List<String> = context?.let { viewModel.prepareQuoteList(it) }!!.toList()

        // slidesrecyclerView is the binding name gave to recyclerview id in  fragment_manual_sliding_recyclerview
        bindingManual.slidesRecyclerview.adapter = context?.let { SlidingItemAdapter(imgList, manualQuoteList, this) }


        val pgSnaphelper: SnapHelper = PagerSnapHelper()

        // By using a pagerSnap Helper the snap goes strictly to only 1 slide - not scrolling through many more
        bindingManual.slidesRecyclerview.layoutManager?.let {
            bindingManual.slidesRecyclerview.layoutManager!!.getChildAt(0)
                ?.let { it1 -> pgSnaphelper.calculateDistanceToFinalSnap(it, it1) }
            }
        pgSnaphelper.attachToRecyclerView(bindingManual.slidesRecyclerview)
        }
    }

override fun draOnItemClick(position: Int) {
        Toast.makeText(context, "Item saved!", Toast.LENGTH_SHORT).show()
        val clickedImg = imgList[position]

        // creating the quote in the viewmodel ( I hope)
        val quoteList = context?.let { viewModel.prepareQuoteList(it) }

        // getting the right quote
        val clickedQuote = quoteList?.get(position).toString()

        // adding the item to the database
        viewModel.addNewItem(clickedImg, clickedQuote)

        // standard implementation
        bindingManual.slidesRecyclerview.adapter?.notifyItemChanged(position)
    }
0 Answers
Related