Reputation: 3031
When TextView containing chat message is having content more than accommodatable in one line, the text view stops listening for clicks and long clicks. I tried to listen same events on the parent item of TextView, but it's not working there as well. This is the code:
<TextView
android:id="@+id/message_text_view"
android:background="@drawable/bubble_right"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/open_sans"
android:layout_marginStart="17dp"
android:layout_marginEnd="5dp"
android:paddingTop="8sp"
android:paddingBottom="8sp"
android:paddingStart="20sp"
android:paddingEnd="20sp"
android:text="@string/hello"
android:textColor="@color/white"
android:textSize="16sp" />
Java code:
messageRightBinding.messageTextView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
messageRightBinding.messageTextView.setVisibility(View.VISIBLE);
return true;
}
});
Full XML layout file:
<?xml version="1.0" encoding="utf-8"?>
<layout
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"
tools:context=".ChatActivity">
<data>
<import type="android.view.View"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/conversation_time"
android:visibility="gone"
android:layout_margin="20sp"
android:textSize="14sp"
android:layout_gravity="center"
android:gravity="center"
android:textAlignment="center"
android:text="2 July, 2018"
android:textColor="@color/light_black"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="end|center_vertical"
android:padding="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:id="@+id/message_holder">
<TextView
android:id="@+id/message_text_view"
android:background="@drawable/bubble_right"
android:clickable="false"
android:focusable="false"
android:longClickable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/open_sans"
android:layout_marginStart="17dp"
android:layout_marginEnd="5dp"
android:paddingTop="8sp"
android:paddingBottom="8sp"
android:paddingStart="20sp"
android:paddingEnd="20sp"
android:text="@string/hello"
android:textColor="@color/white"
android:textSize="16sp" />
</RelativeLayout>
<LinearLayout
android:visibility="gone"
android:id="@+id/message_button_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:background="@drawable/rounded_whitebackground"
android:backgroundTint="@color/dark_pink"
android:id="@+id/unsend_button_right"
android:layout_width="90sp"
android:layout_height="40sp"
android:layout_marginEnd="5sp"
android:textColor="@color/white"
android:textSize="16sp"
android:fontFamily="@font/open_sans"
android:padding="6sp"
android:text="@string/unsend" />
<Button
android:background="@drawable/rounded_whitebackground"
android:backgroundTint="@color/dark_pink"
android:id="@+id/unsend_button_right_hide"
android:layout_width="30sp"
android:layout_height="40sp"
android:textColor="@color/white"
android:textSize="16sp"
android:padding="8sp"
android:fontFamily="@font/open_sans"
android:text="@string/x" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:clickable="false"
android:focusable="false"
android:gravity="center_vertical|end"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:clickable="true"
android:longClickable="true"
android:focusable="true"
android:id="@+id/time_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/roboto"
android:text="@string/_11_00pm"
android:textColor="@color/light_black"
android:textSize="12sp" />
<ImageView
android:clickable="false"
android:focusable="false"
android:id="@+id/indicator_image_view"
android:layout_margin="2sp"
android:layout_width="12sp"
android:layout_height="12sp"
android:tint="@color/light_black"
app:srcCompat="@drawable/ic_check_black_24dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>
Full RecyclerView code
package batteries;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import com.titanictek.titanicapp.R;
import com.titanictek.titanicapp.databinding.MessageLeftBinding;
import com.titanictek.titanicapp.databinding.MessageRightBinding;
import com.titanictek.titanicapp.db.AppDatabase;
import com.titanictek.titanicapp.db.Contacts;
import com.titanictek.titanicapp.db.DatabaseInstance;
import com.titanictek.titanicapp.db.NewMessage;
import com.titanictek.titanicapp.fragment.ChatFragment2;
import com.titanictek.titanicapp.services.WebSocketTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class ChatMessageRecyclerAdapter2 extends RecyclerView.Adapter{
Context context;
private UUID userId;
// private String threadId;
private Contacts contact;
private ArrayList<NewMessage> newMessages;
private static final int MESSAGE_SENT = 1;
private static final int MESSAGE_RECEIVED = 2;
final private RecyclerView recyclerView;
final ChatFragment2.OnSeenCallback onSeen;
public ChatMessageRecyclerAdapter2(Context context, UUID userId, String threadId, Contacts contact, RecyclerView recyclerView, ChatFragment2.OnSeenCallback onSeen) {
this.context = context;
this.userId = userId;
// this.threadId = threadId;
this.contact = contact;
this.recyclerView = recyclerView;
this.newMessages = new ArrayList<>();
this.onSeen = onSeen;
}
public void setContact(Contacts contact) {
this.contact = contact;
}
public void addMessagesFirst(List<NewMessage> messages) {
newMessages.addAll(0, messages);
// recyclerView.getLayoutManager().fi
notifyDataSetChanged();
recyclerView.scrollToPosition(messages.size()+5);
}
// todo: Add SCROLL logic
public void clearMessages() {
newMessages.clear();
notifyDataSetChanged();
scrollToBottom();
}
public void addMessagesInLast(List<NewMessage> messages) {
newMessages.addAll(messages);
notifyDataSetChanged();
scrollToBottom();
}
public void addMessage(NewMessage message) {
newMessages.add(message);
notifyDataSetChanged();
scrollToBottom();
}
public void onMessageSeen(ArrayList<String> messageIds) {
int c = messageIds.size();
for (NewMessage message: newMessages) {
if (messageIds.contains(message.getMessageId())) {
message.setReached(3);
c--;
if (c==0) break;
}
}
if (c < messageIds.size()) notifyDataSetChanged();
}
public void onMessageSent(WebSocketTypes.ChatMessageDeliveryStatus status) {
for (NewMessage message: newMessages) {
if (message.getMessageId().equals(status.refId.toString())) {
message.setReached(1);
message.setMessageId(status.messageId.toString());
notifyDataSetChanged();
break;
}
}
}
public void onMessageDelivered(String messageId) {
for (NewMessage message: newMessages) {
if (message.getMessageId().equals(messageId)) {
message.setReached(2);
notifyDataSetChanged();
break;
}
}
}
public void addMessagesInLast(NewMessage ...messages) {
final int oldSize = newMessages.size();
newMessages.addAll(Arrays.asList(messages));
// notifyDataSetChanged();
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return oldSize;
}
@Override
public int getNewListSize() {
return newMessages.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return newItemPosition < oldSize;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return newItemPosition < oldSize;
}
});
diffResult.dispatchUpdatesTo(this);
scrollToBottom();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == MESSAGE_SENT){
return new SendMessageHolder(MessageRightBinding.inflate(
LayoutInflater.from(context), parent, false)
);
} else {
return new ReceiveMessageHolder(MessageLeftBinding.inflate(
LayoutInflater.from(context), parent, false)
);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
NewMessage message = newMessages.get(position);
if(message.getUserId().equals(userId.toString())){
((SendMessageHolder) holder).bind(message, position);
} else {
if (!message.isSeen()) {
message.setReached(3);
onSeen.run(message);
}
((ReceiveMessageHolder) holder).bind(message, position);
}
}
public void scrollToBottom() {
if (getItemCount() > 0) {
Log.w("SCROLL", "DONE");
recyclerView.smoothScrollToPosition(getItemCount());
}
}
@Override
public int getItemViewType(int position) {
NewMessage newMessage = newMessages.get(position);
if (newMessage.getUserId().equals(userId.toString())) {
return MESSAGE_SENT;
} else {
return MESSAGE_RECEIVED;
}
}
private int getItemViewType(NewMessage newMessage) {
//Log.w("NewMessage SentBy", newMessage.getUserId());
//Log.w("NewMessage Received By", contacts.getId());
if (newMessage.getUserId().equals(userId.toString())) {
return MESSAGE_SENT;
} else {
return MESSAGE_RECEIVED;
}
}
@Override
public int getItemCount() {
return newMessages.size();
}
private class SendMessageHolder extends RecyclerView.ViewHolder{
private MessageRightBinding messageRightBinding;
SendMessageHolder(MessageRightBinding binding) {
super(binding.getRoot());
this.messageRightBinding = binding;
}
public void bind(NewMessage newMessage, int position){
// messageRightBinding.mes.setText(newMessage.getText());
messageRightBinding.messageTextView.setText(newMessage.getText());
/*Picasso.rest().load(contacts.getProfilePicture()).resize(50, 50).
into(messageRightBinding.messageRightPp);*/
if (newMessage.isSeen()) {
messageRightBinding.indicatorImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_eye_black_24dp));
} else {
if (newMessage.isSent())
messageRightBinding.indicatorImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_check_black_24dp));
else // if (newMessage.isSentFailed())
messageRightBinding.indicatorImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_access_time_black_24dp));
}
messageRightBinding.timeTextView.setText(ContentUtils.getTime(newMessage.getTime()));
long lastTime = 0;
messageRightBinding.conversationTime.setVisibility(View.GONE);
if (position != 0) {
lastTime = ChatMessageRecyclerAdapter2.this.newMessages.get(position - 1).getTime();
if (newMessage.getTime() - lastTime >= 20000000) {
messageRightBinding.conversationTime.setText(new Date(newMessage.getTime()).toString());
messageRightBinding.conversationTime.setVisibility(View.VISIBLE);
}
} else {
messageRightBinding.conversationTime.setText(new Date(newMessage.getTime()).toString());
messageRightBinding.conversationTime.setVisibility(View.VISIBLE);
}
messageRightBinding.messageButtonHolder.setVisibility(View.GONE);
messageRightBinding.messageHolder.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
messageRightBinding.messageButtonHolder.setVisibility(View.VISIBLE);
return true;
}
});
messageRightBinding.unsendButtonRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
messageRightBinding.unsendButtonRight.removeCallbacks(null);
// newMessages.remove(position);
newMessages.remove(position);
notifyDataSetChanged(); // position -1, newMessages.size() - position );
Toast.makeText(context, "Unsending the message", Toast.LENGTH_SHORT).show();
}
});
messageRightBinding.unsendButtonRightHide.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
messageRightBinding.messageButtonHolder.setVisibility(View.GONE);
}
});
}
}
private class ReceiveMessageHolder extends RecyclerView.ViewHolder{
private MessageLeftBinding messageLeftBinding;
ReceiveMessageHolder(MessageLeftBinding binding) {
super(binding.getRoot());
this.messageLeftBinding = binding;
}
public void bind(NewMessage newMessage, int position){
messageLeftBinding.messageTextView.setText(newMessage.getText());
if (position +1 < ChatMessageRecyclerAdapter2.this.getItemCount() && contact != null)
if (ChatMessageRecyclerAdapter2.this.getItemViewType(position+1) != MESSAGE_RECEIVED)
{
Picasso.get().load(contact.getProfilePicture()).resize(50, 50).
into(messageLeftBinding.messageLeftPp);
messageLeftBinding.messageLeftPp.setVisibility(View.VISIBLE);
}
else
messageLeftBinding.messageLeftPp.setVisibility(View.VISIBLE);
else if(contact != null) {
Picasso.get().load(contact.getProfilePicture()).resize(50, 50).
into(messageLeftBinding.messageLeftPp);
messageLeftBinding.messageLeftPp.setVisibility(View.VISIBLE);
}
long lastTime = 0;
messageLeftBinding.conversationTime.setVisibility(View.GONE);
if (position != 0) {
lastTime = ChatMessageRecyclerAdapter2.this.newMessages.get(position - 1).getTime();
if (newMessage.getTime() - lastTime >= 20000000) {
messageLeftBinding.conversationTime.setText(new Date(newMessage.getTime()).toString());
messageLeftBinding.conversationTime.setVisibility(View.VISIBLE);
}
} else {
messageLeftBinding.conversationTime.setText(new Date(newMessage.getTime()).toString());
messageLeftBinding.conversationTime.setVisibility(View.VISIBLE);
}
messageLeftBinding.timeTextView.setText(ContentUtils.getTime(newMessage.getTime()));
}
}
}
Screenshot:
Here the Unsend and X button come on long click, but that works only for one liner messages.
Any help or suggestion will be appreciated and I will be very thankful.
Upvotes: 0
Views: 149
Reputation: 3031
Sorry everyone for wasting your time and frying your heads for a problem which was not there actually. Those two buttons "Unsend" and "X" were not visible because when the TextView got content in length more than a line, it's was using the full width of screen leaving no space for other things. Hence even when the button's state was visible the buttons were not there in view port. Causing this so lengthy discussion and a misleading question title.
Finally this worked for me:
<LinearLayout
android:layout_width="match_parent"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="end|center_vertical"
android:padding="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:id="@+id/message_holder"
android:clickable="true"
android:focusable="true"
android:longClickable="true">
<TextView
android:id="@+id/message_text_view"
android:background="@drawable/bubble_right"
android:clickable="true"
android:focusable="true"
android:longClickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/open_sans"
android:layout_marginStart="17dp"
android:layout_marginEnd="5dp"
android:paddingTop="8sp"
android:paddingBottom="8sp"
android:paddingStart="20sp"
android:paddingEnd="20sp"
android:text="@string/hello"
android:textColor="@color/white"
android:textSize="16sp"
android:layout_toStartOf="@id/message_button_holder"/>
<LinearLayout
android:visibility="gone"
android:id="@+id/message_button_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:background="@drawable/rounded_whitebackground"
android:backgroundTint="@color/dark_pink"
android:id="@+id/unsend_button_right"
android:layout_width="90sp"
android:layout_height="40sp"
android:layout_marginEnd="5sp"
android:textColor="@color/white"
android:textSize="16sp"
android:fontFamily="@font/open_sans"
android:padding="6sp"
android:text="@string/unsend" />
<Button
android:background="@drawable/rounded_whitebackground"
android:backgroundTint="@color/dark_pink"
android:id="@+id/unsend_button_right_hide"
android:layout_width="30sp"
android:layout_height="40sp"
android:textColor="@color/white"
android:textSize="16sp"
android:padding="8sp"
android:fontFamily="@font/open_sans"
android:text="@string/x" />
</LinearLayout>
</RelativeLayout>
Sorry to everyone once again.
Upvotes: 0
Reputation: 17854
In your SendMessageHolder
class, replace
messageRightBinding.messageHolder.setOnLongClickListener
with
itemView.setOnLongClickListener
You shouldn't set a long-click listener on a child View in a RecyclerView.
Upvotes: 0
Reputation: 21
try putting your text in a relativelayout and give the click listener to the relative layout
Upvotes: 1
Reputation: 15574
Set android:clickable="true"
and android:longClickable="true"
on your TextView
.
Upvotes: 0