how to implement a SetOnItemClickListener FirebaseRecyclerViewAdapter
Solution 1
There are probably many ways to do this, but this is the one I just quickly tried.
The ChatMessageViewHolder
class has a member field where it keeps the root view for each chat message:
public static class ChatHolder extends RecyclerView.ViewHolder {
View mView;
public ChatHolder(View itemView) {
super(itemView);
mView = itemView;
}
We can use that mView
member to get access to the clickable view. You should add a getter for mView
, but I'm trying to minimize the changes here.
So then in populateView
we can use the overload that has an additional position
parameter and wire things up with an OnClickListener
like this:
mRecycleViewAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, R.layout.message, ChatHolder.class, mChatRef) {
@Override
public void populateViewHolder(ChatHolder chatView, Chat chat, final int position) {
chatView.setName(chat.getName());
chatView.setText(chat.getText());
if (mAuthData != null && chat.getUid().equals(mAuthData.getUid())) {
chatView.setIsSender(true);
} else {
chatView.setIsSender(false);
}
chatView.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.w(TAG, "You clicked on "+position);
mRecycleViewAdapter.getRef(position).removeValue();
}
});
}
};
The answers to this question offer tons of inspiration: RecyclerView onClick. As long as you can determine the position that the user clicked on, you can use the mRecycleViewAdapter.getRef(position)
snippet to get the database reference of the item that was clicked.
Update
On second thought I might like this answer better https://stackoverflow.com/a/26196831/209103:
mMessages.addOnItemTouchListener(new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Log.w(TAG, "You clicked on "+position);
mRecycleViewAdapter.getRef(position).removeValue();
}
}));
It uses the RecyclerItemClickListener
helper class from the answer I linked. And as already said: as long as you have a click/touch listener that tells you the position of the item that was selected, the rest FirebaseUI aspect of it will be the same: call adapter.getRef(position)
to get a database reference for the selected item.
Solution 2
Here is my Solution. This worked for me
ViewHolder Class
public class StudentViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView textViewName;
public TextView textViewRoll;
public TextView textViewAge;
public MyViewHolderClickListener mListener;
private String TAG= getClass().getSimpleName();
public static interface MyViewHolderClickListener{
public void onTextViewNameClick(View view, int position);
public void onTextViewRollClick(View view, int position);
}
public StudentViewHolder(View itemView) {
super(itemView);
textViewName = (TextView) itemView.findViewById(R.id.textViewName);
textViewRoll = (TextView) itemView.findViewById(R.id.textViewRoll);
textViewAge = (TextView) itemView.findViewById(R.id.textViewAge);
textViewName.setOnClickListener(this);
textViewRoll.setOnClickListener(this);
}
public void bindToStudent(Student student){
if (student == null) {
return;
}
textViewName.setText("Name: " + student.getName());
textViewRoll.setText( "Roll: " + student.getRoll());
textViewAge.setText( "Age: " + student.getAge());
}
public void setCustomOnClickListener(MyViewHolderClickListener listener ){
this.mListener = listener;
}
@Override
public void onClick(View view) {
Log.d(TAG, "onClick at " + getAdapterPosition());
Log.d(TAG, "id: " + view.getId());
if( mListener!= null ){
switch (view.getId()) {
case R.id.textViewName:
mListener.onTextViewNameClick(view, getAdapterPosition());
break;
case R.id.textViewRoll:
mListener.onTextViewRollClick(view, getAdapterPosition());
break;
default:
break;
}
}
}
}
Adapter Class
public class StudentListAdapter extends FirebaseRecyclerAdapter<Student, StudentViewHolder> {
Activity parentActivity;
StudentViewHolder.MyViewHolderClickListener myViewHolderClickListener;
private String TAG = getClass().getSimpleName();
public StudentListAdapter(Activity mActivity, Class<Student> modelClass, int modelLayout, Class<StudentViewHolder> viewHolderClass, Query ref) {
super(modelClass, modelLayout, viewHolderClass, ref);
parentActivity = mActivity;
}
@Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
StudentViewHolder viewHolder = super.onCreateViewHolder(parent, viewType);
// adding my MyViewHolderClickListener here
viewHolder.setCustomOnClickListener(myViewHolderClickListener);
return viewHolder;
}
@Override
protected void populateViewHolder(StudentViewHolder viewHolder, final Student model, final int position) {
Log.d(TAG, model.toString());
Log.d(TAG, getRef(position).getKey());
// bind view
viewHolder.bindToStudent(model);
}
public void setMyViewHolderClickListener(StudentViewHolder.MyViewHolderClickListener listener){
this.myViewHolderClickListener = listener;
}
}
In Activity Class
mAdapter = new StudentListAdapter(this, Student.class, R.layout.list_item, StudentViewHolder.class, studentQuery);
mAdapter.setMyViewHolderClickListener(new StudentViewHolder.MyViewHolderClickListener() {
@Override
public void onTextViewNameClick(View view, int position) {
Log.d(TAG, "Name Click at " +position);
}
@Override
public void onTextViewRollClick(View view, int position) {
Log.d(TAG, "Roll Click at " +position);
}
});
recyclerView.setAdapter(mAdapter);
Jonas Rotilli
Updated on December 28, 2020Comments
-
Jonas Rotilli over 3 years
how to implement a SetOnItemClickListener event in a Firebase RecyclerView Adapter? I use the example of documentation, chat app:
private FirebaseRecyclerViewAdapter mAdapter; RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler); recycler.setHasFixedSize(true); recycler.setLayoutManager(new LinearLayoutManager(this)); mAdapter = new FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder>(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) { @Override public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) { chatMessageViewHolder.nameText.setText(chatMessage.getName()); chatMessageViewHolder.messageText.setText(chatMessage.getMessage()); } }; recycler.setAdapter(mAdapter);
-
Jonas Rotilli over 8 yearsFrank, Very good! Thank you! Their two options works perfectly, but in my opinion the first is better, though a little more extensive. For in it the "animation effect" when you click a Recycler view the item works perfectly in the second not. I put the "View mView" in ChatHolder class and added the "chatView.mView.setOnClickListener". To get the position I unlike you, I got this: "recyclerView.getChildPosition (view)" in the "onClick (View view)". Thanks again, and sorry for the delay to validate your answer.
-
Jonas Rotilli over 8 yearsAdding the "Firebase RecyclerView Adapter" class has the method "get Item (position)" that returns the related object. In the example above put in onClick: String myString = getItem (itemPosition);
-
Ali Bdeir over 7 yearsAs usual, you're as useful as hell. You won't believe how much I love your answers.
-
tccpg288 over 7 yearsFrank, much appreciated. Not a huge deal, but the touchListener is almost instantaneous - meaning right when I click the view the action is taken. With this in mind, I am losing some of my material design - for instance, ripple effects on the views are no longer relevant since the touch immediately transitions to the next activity. Any thoughts?
-
Vignesh VRT about 6 yearsint position should not be final. it shows me warning