I have a RecyclerView that gets information from FirebaseFirestore, I need that when I click on an item I change the activity and add a putExtra. I try to call an Intent inside the Adapter of my RecyclerView but I get the error 'Function declaration must have a name' and 'Expecting member declaration'.
How can I change the Activity and add a putExtra by clicking on an Item in the RecyclerView?
this is MyAdapter
package com.example.atipicoapp
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.list_item.view.*
class MyAdapter(private val platoList : ArrayList<Plato>,
private val itemClickListener: OnPlatoClickListener
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
interface OnPlatoClickListener{
fun onItemClick(nombre: String)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
itemView.platoTouch.setOnClickListener(View.OnClickListener { v: View ->
})
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
val plato : Plato = platoList[position]
holder.platoName.text = plato.platoName
holder.platoDescription.text = plato.platoDescription
holder.platoPrecio.text = plato.platoPrecio.toString()
holder.platoCantidad.text = plato.platoCantidad.toString()
}
override fun getItemCount(): Int {
return platoList.size
}
public class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val platoName : TextView = itemView.findViewById(R.id.platoNombre)
val platoDescription : TextView = itemView.findViewById(R.id.platoDescripcion)
val platoPrecio : TextView = itemView.findViewById(R.id.platoPrecio)
val platoCantidad : TextView = itemView.findViewById(R.id.platoCant)
platoCantidad.setOnClickListener(View.OnClickListener {
val intent = Intent(itemView.getContext(),SlotActivity::class.java)itemView.getContext().startActivity(intent)})
}
}
CodePudding user response:
override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
when (holder) {
is MyViewHolder -> {
holder.bind(platoList[position])
}
}
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val platoName : TextView = itemView.findViewById(R.id.platoNombre)
val platoDescription : TextView = itemView.findViewById(R.id.platoDescripcion)
val platoPrecio : TextView = itemView.findViewById(R.id.platoPrecio)
val platoCantidad : TextView = itemView.findViewById(R.id.platoCant)
private val mActivity = itemView.context as Activity
private val intent = Intent(mActivity, SlotActivity::class.java)
fun bind(plato: Plato) {
platoName.text = plato.platoName
platoDescription.text = plato.platoDescription
platoPrecio.text = plato.platoPrecio.toString()
platoCantidad.text = plato.platoCantidad.toString()
platoCantidad.setOnClickListener {
intent.putExtra("key", value)
mActivity.startActivity(intent)
}
}
}
Note: it is much better to use English in variable names and comments so that developers who read your code later can easily understand it.
CodePudding user response:
You're getting an error here because you have two lines of code jammed together on one line.
val intent = Intent(itemView.getContext(),SlotActivity::class.java)itemView.getContext().startActivity(intent)})
A better way to handle this is to expose your click as a listener that the Activity (or Fragment) can implement. It would be more versatile if you change your listener function to use the item type as the parameter instead of a name String explicitly, so I would change it like this. Also, if you mark it as a fun
interface, you can use more concise syntax when you define it in your Activity.
fun interface OnPlatoClickListener{
fun onItemClick(item: Plato)
}
Then in your view holder, add a parameter for the item
so the click listener you put on your view can pass the item to the Activity's OnPlatoClickListener. Mark the view holder class as inner
so it has access to the itemClickListener
property of the adapter.
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
var item: Plato? = null
val platoName : TextView = itemView.findViewById(R.id.platoNombre)
val platoDescription : TextView = itemView.findViewById(R.id.platoDescripcion)
val platoPrecio : TextView = itemView.findViewById(R.id.platoPrecio)
val platoCantidad : TextView = itemView.findViewById(R.id.platoCant)
// maybe you should set this on itemView instead so the whole row is clickable
platoCantidad.setOnClickListener {
item?.let(itemClickListener::onItemClick)
}
}
In onBindViewHolder
you need to pass the item to the holder:
override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
val plato : Plato = platoList[position]
with(holder) {
item = plato
platoName.text = plato.platoName
platoDescription.text = plato.platoDescription
platoPrecio.text = plato.platoPrecio.toString()
platoCantidad.text = plato.platoCantidad.toString()
}
}
Then in your Activity (or Fragment), you can set a listener on the adapter when you create it:
val adapter = MyAdapter(theDataList) { clickedItem ->
val name = clickedItem.platoName
val intent = Intent(this@YourActivityName, SlotActivity::class.java)
// do something with name and intent?...
startActivity(intent)
}
// ...