Get Clicked Item and Its Position in Recyclerview

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 to Activity/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 and ViewHolder:

      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 -

  1. The list of Meuble (There is no need to convert this to a TypedArray
  2. 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



Leave a reply



Submit