I am Creating a ChatApp and in which i am getting message of Different type
Text
Image
Audio
Video
I am checking that whether the message is of me or the other user in getItemViewType method of my recyler Adapter and than checking the message type in OnCreateViewholder and passing the particular Binding at runtime so that My App works smoothly but the problem is that The app is lagging when the I click on previous activity item to open my chat activity it takes its sweet time of 1 - 2 seconds and when i am in my Chat Activity the Screen Lags when i scroll the total amount of views which are used in recyler view are 10 5 for sending side and 5 for receiving side
Following is my MessageAdapter Which also contains Viewholder
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import com.example.chat.R;
import com.example.chat.callBacks.SentMessageCallback;
import com.example.chat.databinding.ItemMessageReceiveAudioBinding;
import com.example.chat.databinding.ItemMessageReceiveBinding;
import com.example.chat.databinding.ItemMessageReceiveFileBinding;
import com.example.chat.databinding.ItemMessageReceiveImageBinding;
import com.example.chat.databinding.ItemMessageReceiveVideoBinding;
import com.example.chat.databinding.ItemMessageSentAudioBinding;
import com.example.chat.databinding.ItemMessageSentBinding;
import com.example.chat.databinding.ItemMessageSentFileBinding;
import com.example.chat.databinding.ItemMessageSentImageBinding;
import com.example.chat.databinding.ItemMessageSentVideoBinding;
import com.example.chat.models.Message;
import java.util.ArrayList;
import java.util.List;
//************************************************************
public class MessageAdapter
extends RecyclerView.Adapter
//************************************************************
{
private static final int TYPE_MESSAGE_SENT = 0;
private static final int TYPE_MESSAGE_RECEIVED = 1;
private static final int TYPE_IMAGE_SENT = 2;
private static final int TYPE_IMAGE_RECEIVED = 3;
private static final int MSG_UPDATE_SEEK_BAR = 1845;
Context mContext;
private LayoutInflater inflater;
private List<Message> messageList = new ArrayList<>();
private SentMessageCallback callback;
boolean isNewMessage = false;
Message mMessage;
//************************************************************
public MessageAdapter(Context mContext, LayoutInflater inflater,
SentMessageCallback callback)
//************************************************************
{
this.inflater = inflater;
this.callback = callback;
this.mContext = mContext;
}
//************************************************************
#Override
public int getItemViewType(int position)
//************************************************************
{
mMessage = messageList.get(position);
if (mMessage.isMe()) {
return TYPE_MESSAGE_SENT;
} else {
return TYPE_MESSAGE_RECEIVED;
}
}
//************************************************************
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent,
int viewType)
//************************************************************
{
View view;
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case TYPE_MESSAGE_SENT:
// view = inflater.inflate(R.layout.item_message_sent, parent, false);
switch (mMessage.getType()) {
case "text":
return new SentMessageViewHolder(ItemMessageSentBinding.inflate(layoutInflater, parent, false), mMessage);
case "audio":
return new SentMessageViewHolder(ItemMessageSentAudioBinding.inflate(layoutInflater, parent, false), mMessage);
case "image":
return new SentMessageViewHolder(ItemMessageSentImageBinding.inflate(layoutInflater, parent, false), mMessage);
case "video":
return new SentMessageViewHolder(ItemMessageSentVideoBinding.inflate(layoutInflater, parent, false), mMessage);
case "file":
return new SentMessageViewHolder(ItemMessageSentFileBinding.inflate(layoutInflater, parent, false), mMessage);
}
break;
case TYPE_MESSAGE_RECEIVED:
// view = inflater.inflate(R.layout.item_message_receive, parent, false);
switch (mMessage.getType()) {
case "text":
return new ReceivedMessageHolder(ItemMessageReceiveBinding.inflate(layoutInflater, parent, false), mMessage);
case "audio":
return new ReceivedMessageHolder(ItemMessageReceiveAudioBinding.inflate(layoutInflater, parent, false), mMessage);
case "image":
return new ReceivedMessageHolder(ItemMessageReceiveImageBinding.inflate(layoutInflater, parent, false), mMessage);
case "video":
return new ReceivedMessageHolder(ItemMessageReceiveVideoBinding.inflate(layoutInflater, parent, false), mMessage);
case "file":
return new ReceivedMessageHolder(ItemMessageReceiveFileBinding.inflate(layoutInflater, parent, false), mMessage);
}
break;
}
return null;
}
//************************************************************
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder,
int position)
//************************************************************
{
Message message = messageList.get(position);
holder.setIsRecyclable(false);
if (message.isMe()) {
SentMessageViewHolder messageViewHolder = (SentMessageViewHolder) holder;
messageViewHolder.setData(mContext, message, messageViewHolder, position, callback);
} else {
ReceivedMessageHolder messageHolder = (ReceivedMessageHolder) holder;
messageHolder.setData(mContext, message, messageHolder, position, callback);
}
}
//************************************************************
#Override
public int getItemCount()
//************************************************************
{
return messageList.size();
}
//************************************************************
public void addAllMessages(List<Message> messageList)
//************************************************************
{
this.messageList.addAll(messageList);
notifyDataSetChanged();
}
//************************************************************
public void addNewMessage(Message message, boolean isNewMessage)
//************************************************************
{
messageList.add((message));
this.isNewMessage = isNewMessage;
notifyDataSetChanged();
}
//************************************************************
public void setMargins(View v, int l, int t, int r, int b)
//************************************************************
{
if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
p.setMargins(l, t, r, b);
v.requestLayout();
}
}
//************************************************************
//************************************************************
public static class SentMessageViewHolder
extends RecyclerView.ViewHolder
//************************************************************
//************************************************************
{
TextView messageTxt, textTime;
ImageView text_sendTick;
RelativeLayout textMessageLayout;
ConstraintLayout messageOutGoingLayout;
public View parent;
//************************************************************
public SentMessageViewHolder(#NonNull ItemMessageSentBinding mSentText, Message message)
//************************************************************
{
super(mSentText.getRoot());
parent = itemView;
}
//************************************************************
public SentMessageViewHolder(#NonNull ItemMessageSentAudioBinding mSentAudio, Message message)
//************************************************************
{
super(mSentAudio.getRoot());
parent = itemView;
}
//************************************************************
public SentMessageViewHolder(#NonNull ItemMessageSentImageBinding mSentImage, Message message)
//************************************************************
{
super(mSentImage.getRoot());
parent = itemView;
}
//************************************************************
public SentMessageViewHolder(#NonNull ItemMessageSentVideoBinding mSentVideo, Message message)
//************************************************************
{
super(mSentVideo.getRoot());
parent = itemView;
}
//************************************************************
public SentMessageViewHolder(#NonNull ItemMessageSentFileBinding mSentFile, Message message)
//************************************************************
{
super(mSentFile.getRoot());
parent = itemView;
}
//************************************************************
public void setData(Context context, Message item,
SentMessageViewHolder viewHolder, int itemPosition,
SentMessageCallback callback)
//************************************************************
{
// messageTxt.setText(item.getMessage());
parent.setOnClickListener(v ->
{
callback.onSentMessageClick(item, viewHolder, itemPosition);
});
parent.setOnLongClickListener(v ->
{
callback.onSentMessageLongClick(item, viewHolder, itemPosition);
return false;
});
}
}
//************************************************************
//************************************************************
public static class ReceivedMessageHolder
extends RecyclerView.ViewHolder
//************************************************************
//************************************************************
{
TextView messageTxt, textTime;
RelativeLayout textMessageLayout;
ConstraintLayout incomingMessageLayout;
public View parent;
//************************************************************
public ReceivedMessageHolder(#NonNull ItemMessageReceiveBinding mReceiveText, Message message)
//************************************************************
{
super(mReceiveText.getRoot());
parent = itemView;
}
//************************************************************
public ReceivedMessageHolder(#NonNull ItemMessageReceiveAudioBinding mReceiveAudio, Message message)
//************************************************************
{
super(mReceiveAudio.getRoot());
parent = itemView;
}
//************************************************************
public ReceivedMessageHolder(#NonNull ItemMessageReceiveImageBinding mReceiveImage, Message message)
//************************************************************
{
super(mReceiveImage.getRoot());
parent = itemView;
}
//************************************************************
public ReceivedMessageHolder(#NonNull ItemMessageReceiveVideoBinding mReceiveVideo, Message message)
//************************************************************
{
super(mReceiveVideo.getRoot());
parent = itemView;
}
//************************************************************
public ReceivedMessageHolder(#NonNull ItemMessageReceiveFileBinding mReceiveFile, Message message)
//************************************************************
{
super(mReceiveFile.getRoot());
parent = itemView;
}
//************************************************************
ReceivedMessageHolder(View itemView)
//************************************************************
{
super(itemView);
parent = itemView;
messageTxt = itemView.findViewById(R.id.receivedTxt);
textTime = itemView.findViewById(R.id.textview_time);
textMessageLayout = itemView.findViewById(R.id.textMessageLayout);
incomingMessageLayout = itemView.findViewById(R.id.incoming_layout_bubble);
}
//************************************************************
public void setData(Context context, Message item, ReceivedMessageHolder viewHolder,
int itemPosition, SentMessageCallback callback)
//************************************************************
{
// messageTxt.setText(item.getMessage());
parent.setOnClickListener(v -> {
callback.onReceivedMessageClick(item, viewHolder, itemPosition);
});
parent.setOnLongClickListener(v -> {
callback.onReceivedMessageLongClick(item, viewHolder, itemPosition);
return false;
});
}
}
}
Related
I have a design for messages.
2 xml files are responsible for the design:
recyclerview_item_incoming.xml
recyclerview_item_outgoing.xml
It looks like this:
Messages are stored inside the RecyclerView.
RecyclerView is connected to SQLite via LiveData -> Room.
More Info
To work with the RecyclerView I have 2 classes:
MessageListAdapter:
package com.mardaunt.telesupp.recyclerview;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import com.mardaunt.telesupp.room.Message;
public class MessageListAdapter extends ListAdapter<Message, MessageViewHolder> {
public static int idMessage = 0; // I added that
public static int countMessages = 0; // I added that
public MessageListAdapter(#NonNull DiffUtil.ItemCallback<Message> diffCallback) {
super(diffCallback);
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
countMessages = getItemCount();
//System.out.println(countMessages + " - This countMessages\n" + idMessage + "- This idMessage; " + viewType + " - viewType");
System.out.println(idMessage);
//if(idMessage >= countMessages) idMessage = 0;
// I need to pass the create index method of the current message.!!!!!!!!!!
// The getItem() function returns a Message object.
return MessageViewHolder.create(parent, getItem(idMessage));
}
#Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
Message current = getItem(position);
//System.out.println(current.getId() + " " + current.getPhone() + " " + current.getText());
holder.bind(current.getPhone() ,current.getText()); // Бинтим только тело телефон и сообщение!
idMessage = position+1;
if(idMessage >= countMessages) idMessage = 0;
}
public static class MessageDiff extends DiffUtil.ItemCallback<Message> {
#Override
public boolean areItemsTheSame(#NonNull Message oldItem, #NonNull Message newItem) {
return oldItem == newItem;
}
#Override
public boolean areContentsTheSame(#NonNull Message oldItem, #NonNull Message newItem) {
return oldItem.getText().equals(newItem.getText());
}
}
}
MessageViewHolder:
package com.mardaunt.telesupp.recyclerview;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.mardaunt.telesupp.R;
import com.mardaunt.telesupp.room.Message;
class MessageViewHolder extends RecyclerView.ViewHolder {
private final TextView phoneItemView;
private final TextView messageItemView;
private MessageViewHolder(View itemView) {
super(itemView);
messageItemView = itemView.findViewById(R.id.text_view_message);
phoneItemView = itemView.findViewById(R.id.text_view_phone);
}
public void bind(String phone, String message) {
phoneItemView.setText(phone);
messageItemView.setText(message);
}
//The method decides which design to choose for the message bubble.
static MessageViewHolder create(ViewGroup parent, Message current) {
View view;
if (current.getNature().equals("outgoing"))
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_outgoing, parent, false);
else view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_incoming, parent, false);
return new MessageViewHolder(view);
}
}
And Message:
package com.mardaunt.telesupp.room;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity(tableName = "messages_table")
public class Message {
#PrimaryKey(autoGenerate = true)
private int id;
private String phone;
private String text;
private String nature;
public Message(int id,
#NonNull String phone,
#NonNull String text,
#NonNull String nature
) {
this.id = id;
this.phone = phone;
this.text = text;
this.nature = nature; // incoming OR outgoing
}
public int getId(){return this.id;}
public String getPhone(){return this.phone;}
public String getText(){return this.text;}
public String getNature(){return this.nature;}
}
Problem:
I want the incoming messages to be located on the left. And outgoing messages are located on the right.
To do this, I slightly changed the static method of the MessageViewHolder class:
//The method decides which design to choose for the message bubble.
static MessageViewHolder create(ViewGroup parent, Message current) {
View view;
if (current.getNature().equals("outgoing"))
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_outgoing, parent, false);
else view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_incoming, parent, false);
return new MessageViewHolder(view);
}
But the problem is that I do not know how I can correctly pass the Message objects to this method?
As you can see, I tried to pass the Message object in the MessageListAdapter class:
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
countMessages = getItemCount();
// I need to pass the create index method of the current message.!!!!!!!!!!
// The getItem() function returns a Message object.
return MessageViewHolder.create(parent, getItem(idMessage));
}
#Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
Message current = getItem(position);
holder.bind(current.getPhone() ,current.getText()); // Бинтим только тело телефон и сообщение!
idMessage = position+1;
if(idMessage >= countMessages) idMessage = 0;
}
I added 2 static variable (idMessage, countMessages), but this worked don't correctly.
How I can add Message object for method MessageViewHolder.create(...) ?
Project on GitHub: https://github.com/MinorityMeaning/HelloApp
The getItemViewType() is the right place for determining the item layout. So you need to move the logic there, so override it in the adapter:
#Override
public int getItemViewType(int position) {
if (getItem(position).getNature().equals("outgoing"))
return R.layout.recyclerview_item_outgoing;
else
return R.layout.recyclerview_item_incoming;
}
And that being reflected in the viewType parameter of onCreateViewHolder(), so it holds the right layout for the current item. So you'd pass that to the ViewHolder:
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return MessageViewHolder.create(parent, viewType);
}
And In ViewHolder set that as your layout:
static MessageViewHolder create(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(viewType, parent, false);
return new MessageViewHolder(view);
}
I want to implement a recycler view click event. I intended to have an event when I clicked tvRoomNum. But error 'TextView.setOnClickListener(android.view.View$OnClickListener)' on a null object reference' occurs. So I notice that tvRoomNum is null object and attempt to use 'findViewById'. But the function is not recognized. How can I solve the problem?
public class RoomAdapter extends RecyclerView.Adapter<RoomAdapter.CustomViewHolder> {
private Context context;
private ArrayList<RoomData> rooms;
public ArrayList<StudnetInRoomData> students;
private LayoutInflater inflater;
private RoomData room;
View view;
public RoomAdapter(Context context, ArrayList<RoomData> rooms) {
this.context = context;
this.rooms = rooms;
this.inflater = LayoutInflater.from(context);
students = new ArrayList<>();
}
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
view = inflater.inflate(R.layout.single_room, parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
room = rooms.get(position);
holder.tvRoomNum.setText(String.valueOf(room.roomNum));
}
#Override
public int getItemCount() {
return rooms.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView tvRoomNum;
public CustomViewHolder(View itemView) {
super(itemView);
tvRoomNum.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), PlusStudentActivity.class);
intent.putExtra("studentList", room.students);
context.startActivity(intent);
}
});
}
}
}
The code below is the adapter of the recycler view that implements the recycler view. This is a dual recircular view structure.
public class FloorAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnFloorItemClickListener {
OnFloorItemClickListener listener;
static public ArrayList<FloorData> floors;
private Context context;
private LayoutInflater layoutInflater;
private OnItemClickListener mListener = null;
public FloorAdapter(ArrayList<FloorData> floors, Context context) {
this.floors = floors;
this.context = context;
this.layoutInflater = LayoutInflater.from(context);
}
public interface OnItemClickListener{
void onItemClick(View v, int pos);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener ;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.signle_floor, parent, false);
return new GridViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((GridViewHolder)holder).recyclerView.setAdapter(new RoomAdapter(context, floors.get(position).rooms));
((GridViewHolder)holder).recyclerView.setLayoutManager(new GridLayoutManager(context, 5));
((GridViewHolder)holder).recyclerView.setHasFixedSize(true);
((GridViewHolder)holder).tvFloorNum.setText(String.valueOf(floors.get(position).floorNum));
}
#Override
public int getItemCount() {
return floors.size();
}
#Override public void onItemClick(RecyclerView.ViewHolder holder, View view, int position) {
if(listener != null){
listener.onItemClick(holder,view,position);
}
}
#Override
public int getItemViewType(int position) {
return floors.get(position).id;
}
public class GridViewHolder extends RecyclerView.ViewHolder {
RecyclerView recyclerView;
TextView tvFloorNum;
Button btnPlusRoom;
public GridViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.rvRooms);
tvFloorNum = itemView.findViewById(R.id.tvFloorNum);
btnPlusRoom = (Button)itemView.findViewById(R.id.btnPlusRoom);
btnPlusRoom.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v)
{
int pos = getAdapterPosition();
if (pos != RecyclerView.NO_POSITION)
{
if(mListener != null){
mListener.onItemClick(v, pos);
}
}
}
});
}
}
}
Your TextView is null, because you are missing the findViewById():
You find the Id on a View, in this case, it is the itemView
The function was not recognised because you would've just called findViewById() & ViewHolder does not have that method,
You should've called itemView.findViewById() instead.
Try this:
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView tvRoomNum;
public CustomViewHolder(View itemView) {
super(itemView);
tvRoomNum = itemView.findViewById(R.id.your_textview_id) // THIS
tvRoomNum.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), PlusStudentActivity.class);
intent.putExtra("studentList", room.students);
context.startActivity(intent);
}
});
}
}
So I have a RecyclerView that displays a list of open games in a lobby. Each time the RecyclerView is updated, a button is added to the screen and I want to make it so that whenever a user clicks that button, it gets the ID of the section it is in.
So, games are added to database like this.
public void createLobbyGame () {
User current = new User(userName, 0, getSide());
String id = FCGames.push().getKey();
gameMaker = new GameMaker(current, null, 0, numGames, false, false);
FCGames.child(id)
.setValue(gameMaker).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(FlipCoinLobby.this, "Game creation successful.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(FlipCoinLobby.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
And that creates a node in my database that looks like this:
So right now the ID is set at 0 but that's just because I forgot to make the ID equal to the name of the node.
So when something is added to my database, it is drawn in the app with a button. I am not sure how to make this button display the ID of the database node that it correlates to.
This is the clicklistener I have setup for the button in my ViewHolder class
Button joinButton = itemView.findViewById(R.id.joinRV);
joinButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), gm.getId(), Toast.LENGTH_SHORT).show();
}
});
Just having the getId() method called does not work at all, and I wasn't expecting it to. But I am kind of lost on how to grab the correlating ID of the button whenever I click it
Adapter Class:
package com.example.brent.fifty_fifty;
import android.content.Intent;
import android.util.Log;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.content.Context;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import static android.view.LayoutInflater.*;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
GameMaker gm;
private OnItemClickListener listener;
private List<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, List<String> data) {
this.mInflater = from(context);
this.mData = data;
}
public MyRecyclerViewAdapter(List<String> data, OnItemClickListener listener) {
this.mData = data;
this.listener = listener;
}
public interface OnItemClickListener {
void onItemClick(String id);
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
String userName = mData.get(position);
//Double wager = Double.parseDouble(mData.get(position));
holder.userName.setText(userName);
//holder.wager.setText(wager.toString());
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView userName, wager;
RelativeLayout parentLayout;
ViewHolder(View itemView) {
super(itemView);
userName = itemView.findViewById(R.id.UsernameRV);
//wager = itemView.findViewById(R.id.wagerRV);
itemView.setOnClickListener(this);
Button joinButton = itemView.findViewById(R.id.joinRV);
joinButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onItemClick(data);
Toast.makeText(itemView.getContext(), "It worked", Toast.LENGTH_SHORT).show();
}
});
}
public void bind(final String data, final OnItemClickListener listener) {
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(mData.get(position), listener);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
String getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Please have a look at implementation of interface as Listener for recyclerview.
Please look this implementation. This is good one if you are using JAVA.
Here clicklistener is set on itemView you just need to replace itemView with your button.
public class MyRecyclerViewAdapter extends RecyclerView.Adapter< MyRecyclerViewAdapter.ViewHolder> {
public interface OnButtonClickListener {
void onButtonClick(String id);
}
private final List<String> items;
private final OnButtonClickListener listener;
public MyRecyclerViewAdapter(List<String> items, OnButtonClickListener listener) {
this.items = items;
this.listener = listener;
}
#Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout. recyclerview_row, parent, false);
return new ViewHolder(v);
}
#Override public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(items.get(position), listener);
}
#Override public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private Button joinButton;
public ViewHolder(View itemView) {
super(itemView);
joinButton = (Button) itemView.findViewById(R.id. joinRV);
}
public void bind(final String id, final OnButtonClickListener listener) {
joinButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onItemClick(id);
}
});
}
}}
For your activity :
recycler.setAdapter(new MyRecyclerViewAdapter(items, new MyRecyclerViewAdapter.OnButtonClickListener() {
#Override public void onButtonClick(String id) {
Toast.makeText(this, id, Toast.LENGTH_LONG).show();
}}));
i am working in PopularMovies Project that i used the movies DB
and i was successful fetch the data from the API but when i click the item in RecyclerView it doesn't work.
I have followed the tutorial for udacity
PopularMovies-issue
there is the link of the source code
and this is the adapter
What should I do?
package com.popmov.popmov.popmov
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import com.popmov.popmov.popmov.data.Movie;
import com.squareup.picasso.Picasso;
class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
private final Context context;
private Movie[] moviesData;
public static final String BASE_URL_IMAGE = "http://image.tmdb.org/t/p/w342";
private final MoviesAdapterOnClickHandler moviesAdapterOnClickHandler;
public interface MoviesAdapterOnClickHandler {
void onItemClickListener(int id, String title, String imageUrl, String synopsis, double rating, String releaseDate);
}
public MoviesAdapter(MoviesAdapterOnClickHandler clickHandler,Context context) {
moviesAdapterOnClickHandler = clickHandler;
this.context=context;
}
public class MoviesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final ImageView imageView;
public MoviesViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_view_movie);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
int id = moviesData[adapterPosition].getId();
String title = moviesData[adapterPosition].getTitle();
String imageUrl = moviesData[adapterPosition].getImageUrl();
String synopsis = moviesData[adapterPosition].getSynopsis();
double rating = moviesData[adapterPosition].getRating();
String releaseDate = moviesData[adapterPosition].getReleaseDate();
moviesAdapterOnClickHandler.onItemClickListener(id, title, imageUrl, synopsis, rating, releaseDate);
}
}
#Override
public MoviesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
int layoutForItem = R.layout.movies_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(layoutForItem, viewGroup, false);
return new MoviesViewHolder(view);
}
#Override
public void onBindViewHolder(MoviesViewHolder holder, int position) {
String path = BASE_URL_IMAGE + moviesData[position].getImageUrl();
Picasso.get()
.load(path)
.placeholder(R.mipmap.poster)
.into(holder.imageView);
}
#Override
public int getItemCount() {
if (null == moviesData) {
return 0;
} else {
return moviesData.length;
}
}
}
In your movies_list_item.xml make ImageView clickable to false
android:clickable="false"
As your ImageView clickable property was set to true so your ImageView are absorbing the ClickListener
I am using the method from RecyclerView onClick to perform on item click method in recyclerview. But the problem is how to handle child button in the recyclerview? I have perform onclick method in the adapter but still not work, It always perform recyclerview onitemclicklistener first then only perform onclick method from adapter. How to handle it properly?
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
public void onLongItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
}
}
});
}
#Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
return true;
}
return false;
}
#Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
#Override
public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}
I have implement OnClick in the Adapter Section... Refer to the below code of my Adapter Class
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private Context context;
List<Video_Details> video;
public DataAdapter(List<Video_Details> video, Context context) {
super();
this.context = context;
this.video = video;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_row, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final Video_Details videoDetails = video.get(position);
String url;
final String VideoID;
holder.title.setText(video.get(position).getTitle());
VideoID= video.get(position).getV_id();
url = video.get(position).getThumb();
Glide.with(context)
.load(url)
.override(150,70)
.into(holder.thumb);
//viewHolder.thumb.setText(android.get(i).getVer());
// viewHolder.tv_api_level.setText(android.get(i).getApi());
holder.vm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "You Clicked"+video.get(position).getV_id(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(v.getContext(),Play_Video.class);
intent.putExtra("VideoId",(video.get(position).getV_id()));
intent.putExtra("Title",(video.get(position).getTitle()));
v.getContext().startActivity(intent);
}
}
);
}
#Override
public int getItemCount() {
return video.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView title;
public ImageView thumb;
public String videoid;
public View vm;
public ViewHolder(View view) {
super(view);
vm = view;
title = (TextView)view.findViewById(R.id.title);
thumb = (ImageView) view.findViewById(R.id.thumb);
//tv_version = (TextView)view.findViewById(R.id.tv_version);
//tv_api_level = (TextView)view.findViewById(R.id.tv_api_level);
}
}
}