I'm trying to create behavior similar to what happens in Facebook Messenger, when sending several consecutive messages, so I created several background drawables with border radius
different to be applied to recyclerview
items and give the appearance that one item is related to the other.
There is a addItem
method that is used to post a new item in the conversation and in it I have my logic that checks if the paracarpo of the time of the last message and the current message is less than 5 seconds, and if yes, it is made loop
to iterate the last items in the list and apply the new layout based on some logical tests that will decide if the item will have the top appearance in the group, center or footer, this is done through 4 methods of adaptes
, they are: setItemAsTop
, setItemAsBottom
, setItemAsCenter
and setItemAsSingle
In case the message does not enter the 5s test, these methods simply change the value of a variable and notify the change, variable which is used to apply the layout in the cell in the item in each pass of onBindViewHolder
.
notifyItemChanged
in each of these methods (setItemAs ...) the whole list is notified or I do not know, I do not really understand what is happening, but always the last command setItemAs
.. is applied in the list and not in the past position.
Follow the relevant code from my adapter
:
public class MessageAdapter extends RecyclerView.Adapter {
public class MessageLayoutType {
public static final int AS_TOP = 0;
public static final int AS_CENTER = 1;
public static final int AS_BOTTOM = 2;
public static final int AS_SINGLE = 3;
}
private static java.util.Date lastMessageSendTime = new Date();
private static java.util.Date lastMessageReceiveTime = new Date();
private static int groupCountSend = 0;
private static int groupCountReceived = 0;
private MessageDialogViewHolder holder;
private static int MESSAGE_LAYOUT;
private static int MESSAGE_TYPE = MessageLayoutType.AS_SINGLE;
private static final int SENT_FROM_ME = 1;
private static final int SENT_FROM_OTHER = 2;
private List<Message> messageList;
private OnItemClickListener onItemClickListener;
private User me;
public MessageAdapter() {
this.messageList = new LinkedList<>();
}
public void setOnItemClickListener(MessageAdapter.OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setMe(User me) {
this.me = me;
}
public void addItem(int position, Message message) {
messageList.add(position, message);
notifyItemInserted(position);
if (DateTimeUtils.getDateDiff(lastMessageReceiveTime, message.getTime(), TimeUnit.SECONDS) <= 5) {
groupCountReceived++;
Log.e("===DateTime===", "entrou no time" + groupCountReceived + " e agora o count é " + groupCountReceived );
Log.e("count", groupCountReceived + " ");
for (int i = groupCountReceived; i >= 0; i--) {
if (i == groupCountReceived) {
Log.e("===DateTimeType===", "is top" + i);
this.setItemAsTop(this.getItemCount() - groupCountReceived);
} else if (i >= 1 && i < groupCountReceived) {
Log.e("===DateTimeType===", "is center" + i);
this.setItemAsCenter(this.getItemCount() - i);
} else if (i < 1) {
Log.e("===DateTimeType===", "is bottom" + i);
this.setItemAsBottom(getItemCount());
}
Log.e("===DateTimeFor===", "entrou no time previous message position: " + i);
}
} else {
Log.e("===DateTimeType===", "is alone");
this.setItemAsSingle(this.getItemCount());
groupCountReceived = 0;
}
lastMessageReceiveTime = message.getTime();
}
public void setItemAsTop(int position) {
Log.e("is noticed", " noticed as top");
this.MESSAGE_TYPE = MessageLayoutType.AS_TOP;
Log.e("MessageTYpeChanged", this.MESSAGE_TYPE + "");;
notifyItemChanged(position);
}
public void setItemAsCenter(int position) {
Log.e("is noticed", " noticed as center");
this.MESSAGE_TYPE = MessageLayoutType.AS_CENTER;
Log.e("MessageTYpeChanged", this.MESSAGE_TYPE + "");
notifyItemChanged(position);
}
public void setItemAsBottom(int position) {
Log.e("is noticed", " noticed as bottom");
this.MESSAGE_TYPE = MessageLayoutType.AS_BOTTOM;
Log.e("MessageTYpeChanged", this.MESSAGE_TYPE + "");
notifyItemChanged(position);
}
public void setItemAsSingle(int position) {
Log.e("is noticed", " noticed as single");
this.MESSAGE_TYPE = MessageLayoutType.AS_SINGLE;
Log.e("MessageTYpeChanged", this.MESSAGE_TYPE + "");
notifyItemChanged(position);
}
public void updatedItem(int position) {
notifyItemChanged(position);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final int layout = (viewType == SENT_FROM_ME) ? R.layout.adapter_generic_chat_list_right :
R.layout.adapter_generic_chat_list_left;
return new MessageDialogViewHolder(LayoutInflater.from(parent.getContext()).inflate(layout, parent, false));
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder myholder, int position) {
MESSAGE_LAYOUT = (getItemViewType(position) == SENT_FROM_ME) ? R.drawable.bubble_bg_message_right_alone : R.drawable.bubble_bg_message_left_alone;
final MessageDialogViewHolder holder = (MessageDialogViewHolder) myholder;
final Message message = messageList.get(position);
holder.attachEntity(message);
holder.attachCallBack(onItemClickListener);
Log.e("MessageTYpe", this.MESSAGE_TYPE + "");
if (getItemViewType(position) == SENT_FROM_ME) {
if (this.MESSAGE_TYPE == MessageLayoutType.AS_CENTER) {
Log.e("===DateTimeTypeAdapter=", "is center" + position);
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_right_center;
} else if (this.MESSAGE_TYPE == MessageLayoutType.AS_BOTTOM) {
Log.e("===DateTimeTypeAdapter=", "is bottom" + position);
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_right_bottom;
} else if (this.MESSAGE_TYPE == MessageLayoutType.AS_TOP) {
Log.e("===DateTimeTypeAdapter=", "is top" + position);
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_right_top;
} else {
Log.e("===DateTimeTypeAdapter=", "is alone" + position);
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_right_alone;
}
} else {
if (this.MESSAGE_TYPE == MessageLayoutType.AS_CENTER) {
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_left_center;
} else if (this.MESSAGE_TYPE == MessageLayoutType.AS_BOTTOM) {
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_left_bottom;
} else if (this.MESSAGE_TYPE == MessageLayoutType.AS_TOP) {
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_left_top;
} else {
MESSAGE_LAYOUT = R.drawable.bubble_bg_message_left_alone;
}
}
holder.messageContainer.setBackgroundDrawable(holder.messageContainer.getResources().getDrawable(MESSAGE_LAYOUT));
}
@Override
public int getItemCount() {
return messageList != null ? messageList.size() : 0;
}
@Override
public int getItemViewType(int position) {
if (me.equals(messageList.get(position).getSender())) {
return SENT_FROM_ME;
} else {
return SENT_FROM_OTHER;
}
}
public interface OnItemClickListener {
void onChatMessageItemClick(Message message);
}
static class MessageDialogViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@Bind(R.id.imageContentItem)
ImageView picture;
@Bind(R.id.imageItem)
ImageView imageItem;
@Bind(R.id.descriptionItem)
TextView text;
@Bind(R.id.titleItem)
TextView personName;
@Bind(R.id.spotLastMessageTime)
TextView messageTime;
@Bind(R.id.is_online)
FrameLayout isOnline;
@Bind(R.id.message_container)
LinearLayout messageContainer;
@Bind(R.id.layoutChatImageContainer)
LinearLayout layoutChatImageContainer;
@Bind(R.id.message_name_time_container)
LinearLayout messageNameTimeContainer;
private Message message;
private OnItemClickListener onItemClickListener;
public MessageDialogViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
}
public void attachEntity(Message message) {
this.message = message;
}
public void attachCallBack(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public void onClick(View view) {
onItemClickListener.onChatMessageItemClick(message);
}
}
}