I'm laying out 3 views horizontally on the screen (fixed-size image and 2 single-line text views: leftTextView
and rightTextView
) and I'm trying to get the rightTextView
to hug against the leftTextView
, but in the event that the width of both labels would exceed the screen size, truncate the leftTextiew
.
Example of desired functionality:
|img|leftText|rightText| ||(end of screen)
|img|leftTextMedium|rightText| ||
|img|leftTextTooLongSoTrunc...|rightText||
What's actually happening:
|img|leftText|rightText| ||(end of screen)
|img|leftTextPrettyLongButNotHuge|rightT||
|img|leftTextWhichIsIncrediblyLongBlahBl||
Currently, if the size of both text views exceeds the view's width, the rightTextView
ends up getting squished down to make room, even though I've set android:ellipsize="end"
on the leftTextView
.
Is there a way to make the leftTextView
have a "truncation priority" that says it should truncate if it would cause other views to not fit? Or on the other side, can I set the rightTextView
to have a "compression resistance" in order to keep it from being squished to make room for the leftTextView
? Here's a sample of my XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/fixedWidthImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/leftTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/fixedWidthImage"
android:layout_toRightOf="@id/fixedWidthImage"
android:maxLines="1"
android:textSize="18sp"
android:ellipsize="end" />
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/leftTextView"
android:layout_toRightOf="@+id/leftTextView"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:maxLines="1"
android:textSize="12sp" />
</RelativeLayout>
Things I've tried:
leftTextView
, add a toStartOf
/ toLeftOf
the rightTextView
(crashes the app)Instead of aligning the rightTextView
to the end/right of the leftTextView
, flip it and align the leftTextView
to the start/left of the rightTextView
. This results in the rightTextView
being anchored to the end of the screen instead of directly to the right of the leftTextView
. Example of how this ends up looking:
|img|leftText |rightText||
|img|leftTextMedium |rightText||
|img|leftTextTooLongSoTrunc...|rightText||
Even if I set android:minWidth="25dp"
just to ensure at least part of the rightTextView
is visible (which I don't want to do because this text length is variable) it still ends up compressing the width to make room for the leftTextView
.
LinearLayout
and setting the weight on the leftTextView
. The result was visually identical to what I tried in #2.You can archive this layout by TableLayout
and shrinkColumns
attribute.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Row 1 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="leftText"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
<!-- Row 2 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="leftTextPrettyLongButNotHuge"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
<!-- Row 3 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="leftTextWhichIsIncrediblyLongBlahBlahBlahBlah"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
</LinearLayout>
Here's what I do:
<?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="horizontal">
<ImageView
android:id="@+id/fixedWidthImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher_pro" />
<TextView
android:id="@+id/leftTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical|left"
android:ellipsize="marquee"
android:lines="1"
android:text="This is a very long text, and now even longer" />
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|left"
android:lines="1"
android:text="This is also quite long" />
</LinearLayout>
The android:layout_weight="1" does the "trick" here. The documentation isn't quite clear on this one though:
For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content.
(https://developer.android.com/guide/topics/ui/layout/linear.html#Weight)
It doesn't elaborate on the case in which there isn't space to fill but not enough space for all views. One interpretation of the mentioned piece of documentation would be that a field without weight (the rightTextView in this case) will occupy the area required by its content while a field with weight (the leftTextView in this case) will "grow" (as in negative growth) and that's exactly what happens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With