Problem with text alignment in a chat bubble layout

from the CommonsWare Community archives

At October 26, 2019, 11:45am, Shahood asked:

Hi,

Here is a simple layout for sender’s chat messages:

<?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:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end"
    android:background="@android:color/holo_green_light"
    android:layout_margin="8dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="8dp"
        android:paddingEnd="8dp"
        android:paddingStart="8dp"
        android:text="Hello world"
        android:textAlignment="textStart"
        android:textColor="@android:color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <TextView
        android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="July 30, 2019"
        android:textColor="@android:color/black"
        android:textSize="10dp"
        android:paddingEnd="8dp"
        android:paddingStart="8dp"
        android:paddingBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/message" />

</androidx.constraintlayout.widget.ConstraintLayout>

What I need to achieve is that message text is aligned to the left (in case of left-to-right languages) but since message TextView is anchored to the end of the parent, the text appears at the right whenever the message TextView width is smaller than date TextView.

So, following are the results when the message text is “Hello world” and “Hi”. In both cases, message text is anchored to the end but the effect is apparent in case of “Hi” where the width is smaller than date:

Please suggest how to fix this!

Thanks


At October 26, 2019, 11:59am, mmurphy replied:

Off the cuff, anchor both TextView widgets to both sides of the ConstraintLayout, and use bias to determine where in horizontal space the text goes. Set the bias to 0 if you want the text to be shifted towards the start side of the available space.

Also, I really recommend that you use start/end consistently. Your layout is mixing start/end with left/right.


At October 26, 2019, 12:12pm, Shahood replied:

Good idea! It works in case of LTR languages but not in case of RTL. For example, Urdu appears like this, where it should be anchored to the right:

Would I have to change the bias programatically be checking it the text being displayed is RTL or LTR?

Also, I really recommend that you use start/end consistently. Your layout is mixing start/end with left/right.

Yeap I always use start and end. It is just that ConstraintLayout, by default, forces constraints using right and left instead of start and end.


At October 26, 2019, 12:40pm, mmurphy replied:

Hmmm… if your anchors are start/end, the bias should be start/end. This is why I pointed out that you need to be consistent. If you want to support RTL, you need to stop using right/left in your layout.

Not in the code in your original question on this thread. You have app:layout_constraintRight_toRightOf in two places.


At October 26, 2019, 12:46pm, mmurphy replied:

Google mentions ConstraintLayout RTL fixes in the 2.0.0 series. You might try implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta3" and see you get better bias results.


At October 26, 2019, 12:57pm, mmurphy replied:

Another solution is to keep your anchors on start/end, leave the bias alone, set the width to 0dp (so the TextView fills the horizontal space), and use android:gravity="start" on the TextView widgets.


At October 26, 2019, 1:15pm, Shahood replied:

Even in this case, I would have to change the gravity to end dynamically for RTL languages.


At October 26, 2019, 1:23pm, Shahood replied:

Solved the issue as follows:

clTextContainer is the ConstraintLayout to which the TextView is anchored.

It works perfectly for both LTR and RTL languages.

Thanks for all the help!


At October 26, 2019, 1:29pm, mmurphy replied:

No, because the meaning of “end” is tied to language direction.


At October 26, 2019, 1:40pm, Shahood replied:

If I set layout_width of both TextView to 0dp, both disappear probably because the ConstraintLayout width is set to wrap_content. If I set layout_width of only message TextView to 0dp and keep that of date to wrap_content, width of the whole layout is somehow set to the width of date TextView. If text in message TextView is large, it gets wrapped as shown below:

Or am I doing something wrong?


At October 26, 2019, 2:02pm, mmurphy replied:

Ah, right, I forgot about that. Sorry!