android chat bubble with reply UI

Issue

I’m trying to create a chat bubble with the following code,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/chat_parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:layout_marginStart="64dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="4dp"
        android:background="@drawable/my_text_bg"
        android:elevation="10dp"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/replyUI"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/reply_ui_margin"
            android:layout_marginTop="@dimen/reply_ui_margin"
            android:layout_marginEnd="@dimen/reply_ui_margin"
            android:layout_marginBottom="@dimen/reply_ui_minus_margin"
            android:background="@drawable/reply_box_bg_sent"
            android:clickable="true"
            android:elevation="@dimen/reply_ui_elevation"
            android:focusable="true"
            android:foreground="?android:attr/selectableItemBackground"
            android:orientation="vertical"
            android:padding="@dimen/reply_ui_padding"
            android:visibility="gone">


            <TextView
                android:id="@+id/replyToName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:maxLines="1"
                android:textColor="?replyTitleSentColor"
                android:textSize="@dimen/chat_reply_to_text_size" />

            <TextView
                android:id="@+id/replyToTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:maxLines="1"
                android:textColor="?replyTxtColor"
                android:textSize="@dimen/chat_reply_to_text_size" />
        </LinearLayout>

        <TextView
            android:id="@+id/sentTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/chat_text_margin_start"
            android:layout_marginTop="@dimen/chat_text_margin"
            android:layout_marginEnd="@dimen/chat_text_margin"
            android:layout_marginBottom="@dimen/chat_text_margin"
            android:autoLink="all"
            android:textColor="?chatTxtColor"
            android:textColorLink="?attr/chatLinkColorSent"
            android:textSize="@dimen/chat_text_size" />


    </LinearLayout>


    <TextView
        android:id="@+id/timeStamp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:layout_marginEnd="@dimen/chat_timestamp_text_margin"
        android:layout_marginBottom="@dimen/chat_timestamp_text_margin"
        android:drawablePadding="@dimen/chat_timestamp_drawable_padding"
        android:textColor="@color/grey"
        android:textSize="@dimen/chat_timestamp_text_size" />

</LinearLayout>

And it produces the following output,
chat bubble
As you can see, the replyUI is not filling the entire width of the chat bubble.

So, I tried setting replyUI width to match_parent, it fills the parent and the output looks like this,
chat bubble 2

But now I have another problem, If the sentTxt text is too short it shrinks the whole layout and replyUI is not readable at all. See below image.chat bubble 3

How can I get the replyUI to fill the entire bubble width without shrinking when sentTxt is too short? I tried to set a minWidth property, but that didn’t work. Any help appreciated.

Solution

I think it would be better for you to use ConstraintLayout in this case.

You want the replyUI width to always match the constraint making it go until to the end of chat_parent but at the same time you want its minimum width constrained to its own content width.

chat_parent width needs to be wrap_content, it will have the width decided by either replyUI (if replyToTxt is longer than the sentTxt) or sentTxt (if sentTxt is longer than replyToTxt)

Using app:layout_constraintWidth_min="wrap" in replyUI is the key to achieving the desired effect

I’ve played around a little bit changing the dimension, drawables and color values of your snippet just to give you an example. You would probably need to tweak some values (like gravity, maxLines, maxWidth and constraints margins)

Short Reply vs Long Sent Text

Short Reply vs Long Sent Text

Long Reply vs Short Sent Text
Long Reply Short Sent Text

Here is the .xml for these

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/chat_parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="8dp"
        android:background="@color/purple_500"
        android:elevation="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/replyUI"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="4dp"
            android:background="@color/purple_200"
            android:clickable="true"
            android:elevation="4dp"
            android:focusable="true"
            android:foreground="?android:attr/selectableItemBackground"
            android:maxWidth="160dp"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintWidth_min="wrap">


            <TextView
                android:id="@+id/replyToName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="4dp"
                android:layout_marginTop="4dp"
                android:layout_marginEnd="8dp"
                android:ellipsize="end"
                android:maxLines="1"
                android:textColor="@color/purple_500"
                android:textSize="12sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="You" />

            <TextView
                android:id="@+id/replyToTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="4dp"
                android:layout_marginTop="4dp"
                android:layout_marginEnd="4dp"
                android:layout_marginBottom="4dp"
                android:maxWidth="160dp"
                android:textColor="@color/white"
                android:textSize="13sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/replyToName"
                tools:text="This is a long text" />
        </androidx.constraintlayout.widget.ConstraintLayout>

        <TextView
            android:id="@+id/sentTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="4dp"
            android:layout_marginBottom="4dp"
            android:autoLink="all"
            android:maxWidth="160dp"
            android:textColor="@color/white"
            android:textColorLink="@color/purple_500"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/replyUI"
            tools:text="Hi" />


    </androidx.constraintlayout.widget.ConstraintLayout>


    <TextView
        android:id="@+id/timeStamp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginBottom="4dp"
        android:drawablePadding="4dp"
        android:textColor="@color/white"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/chat_parent"
        app:layout_constraintTop_toBottomOf="@+id/chat_parent"
        tools:text="13:45" />

</androidx.constraintlayout.widget.ConstraintLayout>

Answered By – cesonha

Answer Checked By – Senaida (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *