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)
}