Ravinder Payal
Ravinder Payal

Reputation: 3031

Android: TextView having text of more than one line is not clickable/long clickable

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. enter image description here

Any help or suggestion will be appreciated and I will be very thankful.

Upvotes: 0

Views: 149

Answers (4)

Ravinder Payal
Ravinder Payal

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>

enter image description here

Sorry to everyone once again.

Upvotes: 0

TheWanderer
TheWanderer

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

Joe Mobarak
Joe Mobarak

Reputation: 21

try putting your text in a relativelayout and give the click listener to the relative layout

Upvotes: 1

Gokul Nath KP
Gokul Nath KP

Reputation: 15574

Set android:clickable="true" and android:longClickable="true" on your TextView.

Upvotes: 0

Related Questions