Home > database >  How to pass data from RecyclerView's click listener to another fragment?
How to pass data from RecyclerView's click listener to another fragment?

Time:11-10

In my program i have a RecyclerView with adapter, in which i'm checking which element of RecyclerView is clicked.

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val currentBreakfast = breakfastList[position]
    holder.breakfastTitle.text = context.getText(currentBreakfast.breakfastStringResourceId)
    holder.breakfastImage.setImageResource(currentBreakfast.breakfastImageResourceId)

    holder.breakfastImage.setOnClickListener {
        holder.itemView.findNavController().navigate(R.id.action_breakfastFragment_to_DetailsFragment)
        showDetails(currentBreakfast)
    }
}

I want to pass the data about specific clicked element, such as imageId, stringId, Name, etc. to another fragment DetailsFragment in which i would like to display further data

How can i do it?

CodePudding user response:

You need to send your fragment to the adapter from where you are calling i guess it's breakfastFragment, just add this to it:

            YourAdapter(
                requireActivity(),
                breakfastList,
                this
            )

And your Adapter get that fragment:

open class YourAdapter(
    private val context: Context,
    private var breakfastList: ArrayList<Breakfast>,
    private val fragment: Fragment
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

And you can use that fragment to be able to navigate from it:

holder.breakfastImage.setOnClickListener {
// create a bundle to hold data you want to send
 val bundle = bundleOf(
   "imageId" to currentBreakfast.imageId,
   "stringId" to currentBreakfast.stringId,
   "name" to currentBreakfast.name
 )
// add this bundle when you move to another fragment.              
fragment.findNavController().navigate(R.id.action_breakfastFragment_to_DetailsFragment, bundle)
}

In another fragment get that value and see them in the Log like below:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        arguments?.let {
            if (it["imageId"] != null) {
                Log.e("imageId", it.getString("imageId")!!.toString())
            }
            if (it["stringId"] != null) {
                Log.e("stringId", it.getString("stringId")!!.toString())
            }
            if (it["name"] != null) {
                Log.e("name", it.getString("name")!!.toString())
            }
        }
        return inflater.inflate(R.layout.fragment_question_stats, container, false)
    }

P.S. I just made up some variable and class names because you did not share them, just change it with yours correct ones.

CodePudding user response:

There are several ways to it.

I suggest you have a look at this answer (the accepted one) : How to pass data from adapter to fragment?

And then go to the section called "A more Kotlin way to do it is to ignore interfaces and just pass a function instead".

This is the approach I also use myself.

Here is an exampe of how my Adapter for the RecyclerView is defined:

class ReportAdapter(var reports: List<Report>,val clickFunc : (Report) -> (Unit)) :  RecyclerView.Adapter<ReportAdapter.ViewHolder>() {...}

Then you need to attach the callback function to a click listener inside your viewholder - in my example it looks like this (every item in the list has a cardview - defined in the xml file):

itemView.report_cardview_item.setOnClickListener {
                clickFunc(report)
            }

Then in the callback function you pass to the RecylerView Adapter you can navigate to a details fragment with the relevant data - one of my callback functions (which is passed to the Adapter upon creation) simply looks like this (defined in the Fragment that "owns" the RecyclerView):

private fun reportClicked(report:Report)
    {
        val action = ReportsFragmentDirections.actionNavReportsToReportDetailFragment(report)
        findNavController().navigate(action)
    }

(here using my navigation graph to create an Action to use for the NavController)

My adapter is easily initialized with some data and a reference to the callback function:

   adapter = ReportAdapter(reports,::reportClicked)
  • Related