Get clicked item and its position in RecyclerView
Based on the link: Why doesn't RecyclerView have onItemClickListener()? and How RecyclerView is different from Listview?, and also @Duncan's general idea, I give my solution here:
Define one interface
RecyclerViewClickListener
for a passing message from the adapter toActivity
/Fragment
:public interface RecyclerViewClickListener {
public void recyclerViewListClicked(View v, int position);
}In
Activity
/Fragment
implement the interface, and also pass listener to adapter:@Override
public void recyclerViewListClicked(View v, int position){... ...}
//set up adapter and pass clicked listener this
myAdapter = new MyRecyclerViewAdapter(context, this);In
Adapter
andViewHolder
:public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> {
... ...
private Context context;
private static RecyclerViewClickListener itemListener;
public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) {
this.context = context;
this.itemListener = itemListener;
... ...
}
//ViewHolder class implement OnClickListener,
//set clicklistener to itemView and,
//send message back to Activity/Fragment
public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
... ...
public ItemViewHolder(View convertView) {
super(convertView);
... ...
convertView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
itemListener.recyclerViewListClicked(v, this.getPosition());
}
}
}
After testing, it works fine.
[UPDATE]
Since API 22, RecyclerView.ViewHolder.getPosition()
is deprecated, so instead with getLayoutPosition()
.
Get selected item position of RecyclerView
You can use the ViewHolder's getAdapterPosition()
to retrieve the item's position within an interface method. Then store the clicked position in a member variable.
Additionally, there shouldn't be a need to call position++
from within your onBindViewHolder
.
// Create a member variable to store the clicked position
public int clickedPos = -1;
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// ...
holder.addIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// When you're inside the click listener interface,
// you can access the position using the ViewHolder.
// We'll store the position in the member variable in this case.
clickedPos = holder.getAdapterPosition();
}
});
// Remove the 'position++' call as the position should already be handled without explicitly updating it.
}
@Override
public boolean onMenuItemClick(MenuItem item) {
// You can use clickedPos here to perform whatever tasks you need.
// ...
}
How to get the position of an item when i click on it, in a Recyclerview?
In your ExampleViewHolder
:
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextView1;
public TextView mTextView2;
//add this
View view;
public ExampleViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
//set it here
view = itemView;
mImageView = itemView.findViewById(R.id.imageView);
mTextView1 = itemView.findViewById(R.id.textView);
.......
.......
In your adapter
make a constructor that accepts a context
public class ExampleAdapter extends . ........
private Context context;
......
......
//constructor
public ExampleAdapter(.....,Context context){
.........
this.context = context;
}
Pass the context to the constructor, from your activity
//pass the context of the activity here
mAdapter = new ExampleAdapter(exampleList,getApplicationContext());
......
.....
In onBindViewHolder
use the context
to open new activity according to position:
@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mImageView.setImageResource(currentItem.getmImageResource());
holder.mTextView1.setText(currentItem.getmText1());
holder.mTextView2.setText(currentItem.getmText2());
//on click item
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(position == 0){
//first item clicked
context.startActivity(new Intent(context, SomeActivity.class));
}else if(position == 1){
//second item clicked
context.startActivity(new Intent(context, SomeActivity.class));
}else if(position == 2){
//third item clicked
context.startActivity(new Intent(context, SomeActivity.class));
}.......
.......
}
});
}
Get the position of clicked item on Recycler View
Try getAdapterPosition()
from inside the view holder so that you may get the adapter position of the click the user made.
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Toast.makeText(context, String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
}
}
For more in getAdapterPosition() follow this link
Return the correct item position clicked in RecyclerView to another activity
If all you really want is the position of the item then you don't need to send the Meuble on click at all. In your adapter change onBindViewHolder
to:
override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
val currentItem = exampleList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textViewNomMeuble.text = currentItem.nom
holder.textViewPrix.text = currentItem.prix
holder.textViewStock.text = currentItem.stock.toString()
holder.bind(position,listener)
}
Setting your adapter should now look like this:
mon_recycler.adapter = MeubleAdapter(listMeubles.toTypedArray()){ position ->
val intent3 = Intent(this, SceneformeActivity::class.java)
intent3.putExtra("image_url", position)
startActivity(intent3)
}
Edit: Expanding on the adapter usage:
Originally, you are passing two things to your Recyclerview Adapter -
- The list of Meuble (There is no need to convert this to a TypedArray
- The lambda that will act on the click of an item in the list
Consider the refactored code below with my inline comments. Note - it's not clear to me why you are sending position (assuming just to test?) So instead I'm assuming there is some imageURL in the object that you wish to send. I show below how you'd access that.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_liste_meuble3_d)
listMeubles = generateList()
buildRecyclerView()
}
private fun generateList(): MutableList<Meuble>{
val list = mutableListOf<Meuble>()
// to Add an Object Meuble(nom,prix,stock)
val meuble = Meuble(R.drawable.fauteilgris, "Gris","25000da",1)
val meuble1 = Meuble(R.drawable.fauteuille1, "","1000d&",1)
val meuble2 = Meuble(R.drawable.burau, "Bureau","25000da",1)
list.add(meuble)
list.add(meuble1)
list.add(meuble2)
return list
}
fun buildRecyclerView() {
mon_recycler.setHasFixedSize(true)
mon_recycler.layoutManager = LinearLayoutManager(this)
// NOTE: Here the lambda implicitly had an item of type Meuble passed. We name it here but could have just used "it".
mon_recycler.adapter = MeubleAdapter(listMeubles.toTypedArray())
{ item ->
val intent3 = Intent(this, SceneformeActivity::class.java)
intent3.putExtra("image_url",item.imageUrl)
startActivity(intent3)
}
}
}
My Adapter Class .kt:
// Don't need to pass as a TypedArray - List is fine
class MeubleAdapter(private val exampleList: List<Meuble>,val listener: (Meuble)-> Unit) :
RecyclerView.Adapter<MeubleAdapter.ExampleViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExampleViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.meuble_item,
parent, false)
return ExampleViewHolder(itemView)
}
override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
val currentItem = exampleList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textViewNomMeuble.text = currentItem.nom
holder.textViewPrix.text = currentItem.prix
holder.textViewStock.text = currentItem.stock.toString()
holder.bind(exampleList[position],listener)
}
override fun getItemCount() = exampleList.size
class ExampleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(meuble:Meuble,listener: (Meuble) -> Unit)= with(itemView)
{
android.util.Log.i("XXXX","FCT Bind ")
setOnClickListener{(listener(meuble))}
}
val imageView: ImageView = itemView.image_view
val textViewNomMeuble: TextView = itemView.nomMeuble
val textViewStock: TextView = itemView.stock
val textViewPrix: TextView = itemView.prix
}
}
Related Topics
Getting the Physical Screen Dimensions/Dpi/Pixel Density in Chrome on Android
How to Get String Width on Android
How to Save Sms to Inbox in Android
How to Refresh Activity After Changing Language (Locale) Inside Application
How to Programmatically Enable Auto Start and Floating Window Permissions
Placing/Overlapping(Z-Index) a View Above Another View in Android
How to Enable/Disable Bluetooth Programmatically in Android
Draw Multi-Line Text to Canvas
Add and Remove Views in Android Dynamically
Get Gps Location via a Service in Android
Record/Save Audio from Voice Recognition Intent
Android HTML Imagegetter as Asynctask
Listview Setonitemclicklistener Not Working by Adding Button
Android:How to Set Onclick Event for Button in List Item of Listview
How to Use the Simple Http Client in Android