Handle Button Click Inside a Row in Recyclerview

Handle Button click inside a row in RecyclerView

this is how I handle multiple onClick events inside a recyclerView:

Edit : Updated to include callbacks (as mentioned in other comments). I have used a WeakReference in the ViewHolder to eliminate a potential memory leak.

Define interface :

public interface ClickListener {

void onPositionClicked(int position);

void onLongClicked(int position);
}

Then the Adapter :

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

private final ClickListener listener;
private final List<MyItems> itemsList;

public MyAdapter(List<MyItems> itemsList, ClickListener listener) {
this.listener = listener;
this.itemsList = itemsList;
}

@Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_row_layout), parent, false), listener);
}

@Override public void onBindViewHolder(MyViewHolder holder, int position) {
// bind layout and data etc..
}

@Override public int getItemCount() {
return itemsList.size();
}

public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

private ImageView iconImageView;
private TextView iconTextView;
private WeakReference<ClickListener> listenerRef;

public MyViewHolder(final View itemView, ClickListener listener) {
super(itemView);

listenerRef = new WeakReference<>(listener);
iconImageView = (ImageView) itemView.findViewById(R.id.myRecyclerImageView);
iconTextView = (TextView) itemView.findViewById(R.id.myRecyclerTextView);

itemView.setOnClickListener(this);
iconTextView.setOnClickListener(this);
iconImageView.setOnLongClickListener(this);
}

// onClick Listener for view
@Override
public void onClick(View v) {

if (v.getId() == iconTextView.getId()) {
Toast.makeText(v.getContext(), "ITEM PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
}

listenerRef.get().onPositionClicked(getAdapterPosition());
}

//onLongClickListener for view
@Override
public boolean onLongClick(View v) {

final AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle("Hello Dialog")
.setMessage("LONG CLICK DIALOG WINDOW FOR ICON " + String.valueOf(getAdapterPosition()))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {

}
});

builder.create().show();
listenerRef.get().onLongClicked(getAdapterPosition());
return true;
}
}
}

Then in your activity/fragment - whatever you can implement : Clicklistener - or anonymous class if you wish like so :

MyAdapter adapter = new MyAdapter(myItems, new ClickListener() {
@Override public void onPositionClicked(int position) {
// callback performed on click
}

@Override public void onLongClicked(int position) {
// callback performed on click
}
});

To get which item was clicked you match the view id i.e. v.getId() == whateverItem.getId()

Hope this approach helps!

Handle button click inside row in recyclerView

Click listener does not work with a RecyclerView. use OnItemTouchListener()

RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override public void onItemClick(View view, int position) {
// do whatever
}

@Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);

Onclick for each button inside RecyclerView items

If you need in onBindViewHolder only then you can use

holder.getAdapterPosition();

and if you need this position clicked in activity and fragment then you have to use callbacks from holder to activity and fragment and have to pass the same getAdapterPosition();

Edit: Added sample code for listening position click in fragment/activity

step 1: make an interface or callback

public interface RecyclerViewClickListener {

void onClick(View view, int position);
}

step 2: While initializing adapter class in fragment or activity pass the above-created reference as a parameter

public YourAdapter(List<SomeModel> modelList, RecyclerViewClickListener listener){
this.clickListener = listener;
}

step 3: In your ViewHolder or similar Class for view initialization do something like this

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

private Button mapBtn;

ViewHolder(View v, RecyclerViewClickListener listener) {
super(v);
mapBtn = findViewById(R.id.mapBtn);
mListener = listener;
mapBtn.setOnClickListener(this);
}

@Override
public void onClick(View view) {
mListener.onClick(view, getAdapterPosition());
}
}

you will get the position in your fragment or activity where you have passed the callback reference while initializing the adapter.

How to click a button inside a recyclerview item in kotlin

From your code suppose your desired button is myButton and you define it to your adapter like:

    val myButton = itemView.findViewById<Button>(R.id.myButton) // This is your Button, you declared in your xml file.
val fCard = itemView.findViewById<CardView>(R.id.cardOnFront)
val packetTime = itemView.findViewById<TextView>(R.id.timeofPacket)
val timeMessage = itemView.findViewById<TextView>(R.id.messageofTime)
val bCars = itemView.findViewById<CardView>(R.id.backCard)
val drugs = itemView.findViewById<TextView>(R.id.drugs)
val note = itemView.findViewById<TextView>(R.id.note)
val dosage = itemView.findViewById<TextView>(R.id.dosage)

Then just simply call myButton.setOnClickListener inside your initialize function in your adapter like:

    fun intialize(item: PacketModel, action: onPacketItemClickListener) {
var date = (((item.date) as Timestamp).seconds) * 1000L
fun convertLongToTime(time: Long): String {
val date = Date(time)
val format = SimpleDateFormat("yyyy.MM.dd HH:mm")
format.timeZone = TimeZone.getTimeZone("GMT+5")

return format.format(date)
}
var convertedDate = convertLongToTime(date)
packetTime.text = convertedDate
timeMessage.text = ""
drugs.text = item.drugs
note.text = item.notes
dosage.text = item.dosage

itemView.setOnClickListener {
action.onCardClick(item, adapterPosition)
}

myButton.setOnClickListener {
// Do whatever you want on your button click as like you did to your recycler-view item click
//action.onCardClick(item, adapterPosition)
}
}

Button click to use RecyclerView Adapter position

use like this:

holder.itemView.chatView.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mView.getContext(), "person + " + position, Toast.LENGTH_LONG).show();
}
} );

How can I set OnClickListener to two buttons in RecyclerView?

You just need to add some code to your ListAdapter. It is there, where you have to implement onClickListener. The code for your case should look something like the one below.

You can pass any parameter you need to. It depends on the functionality you want to achieve. Here I have demonstrated passing the order of item clicked inside of list.

Option 1 (power/performance efficient)

So, what does the code below actually mean? You have already created a ViewHolder and implemented OnClickListener. That is correct. Now you need to set OnClickListener to two buttons. But what these buttons will do when clicked is defined by the interface we created inside of ViewHolder.

When app will run RecyclerView will create as many ViewHolders as it is needs to fill the available screen with list items by calling onCreateViewHolder() method for each of viewholders. When you scroll up/down these ViewHolders will be reused. OnCreateViewHolder() is not called, only onBindViewHolder() is called to update the content of viewholder. The code below made so that, when ViewHolder is created it will also create an MyClickListener that will be used by OnClickListener of viewholder and when viewholder is reused it will not create new OnClickListener. It means that our method is performance efficient.

Option 2 (not efficient)

You could also setOnClickListener() inside of onBindViewHolder(). However, as I have mentioned in the paragraph above, this method is called every time you scroll to update the content of viewholder. Now it would create new OnClickListener object everytime. While Option 1 has OnClickListener on every ViewHolder and it reuses them.

Code for Option 1

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

private LayoutInflater layoutInflater;
protected Vector<List> lists;

public ListAdapter(Context context, Vector lists) {
layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.lists = lists;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.listadapter, null);
ViewHolder holder = new ViewHolder(view, new MyClickListener() {
@Override
public void onEdit(int p) {
// Implement your functionality for onEdit here
}

@Override
public void onDelete(int p) {
// Implement your functionality for onDelete here
}
});
return holder;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
List list = lists.elementAt(position);
holder.name.setText(list.getName());
}

@Override
public int getItemCount() {
return lists.size();
}

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

MyClickListener listener;

TextView name;
Button edit;
Button delete;

public ViewHolder(View itemView, MyClickListener listener) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.listname);
edit = (Button) itemView.findViewById(R.id.edit);
delete = (Button) itemView.findViewById(R.id.delete);

this.listener = listener;

edit.setOnClickListener(this);
delete.setOnClickListener(this);
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit:
listener.onEdit(this.getLayoutPosition());
break;
case R.id.delete:
listener.onDelete(this.getLayoutPosition());
break;
default:
break;
}
}
}

public interface MyClickListener {
void onEdit(int p);
void onDelete(int p);
}
}

Edit for your second question

To make list items take all the width set the width of your recyclerview to match_parent. It is also better to make it a child view of some layout. For instance as given below.

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.pc.kanayel.runoutof.ShowListOfLists">

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerviewlistas"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

<RelativeLayout>

And change this code inside of your adapter:

View view = layoutInflater.inflate(R.layout.listadapter, null);

to this:

View view = layoutInflater.inflate(R.layout.listadapter, parent, false);

handling click on button inside item of recycler listview

try this:

   @Override
public void onBindViewHolder(MyViewHolder myViewHolder, int i){
myViewHolder.textView.setText(list.get(i));
myViewHolder.btnButton1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
/// button click event
}
});
}

buttons and don't get clicked in recyclerview in adapter

I have finally figured out whats happening, I have been handling lots of things in the foreground, I have transferred lots of them to other threads, now it worked, u might don't believe me, but many really experienced people said to me, that they encountered a very similar situations.



Related Topics



Leave a reply



Submit