Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextView with long text pushes other views off screen

I am trying to achieve the following layout:

+----------------------------------------+
| [icon] [text] [icon]                   |
+----------------------------------------+
| [icon] [very loooooooooooooooooo [icon]|
|         oooooooooooooooong text]       |
+----------------------------------------+

When the text is short, the icon on the right needs to be right next to the text (not right aligned). When the text is long, I need the text to be wrapped.

I have tried to use LinearLayout and RelativeLayout, but the icons are still got pushed out when I have a long text. Here are the layouts I have tried:

LinearLayout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">

    <TextView
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="left"/>

    <TextView
        android:id="@+id/middle"
        android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#D0E198"/>

    <TextView
        android:id="@+id/right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="right"/>
</LinearLayout>

RelativeLayout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">

    <TextView
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="left"/>

    <TextView
        android:id="@+id/middle"
        android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#D0E198"
        android:layout_toRightOf="@id/left"/>

    <TextView
        android:id="@+id/right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="right"
        android:layout_toRightOf="@id/middle"/>
</RelativeLayout>

In both cases, the right icon is pushed out of the screen.

I have also tried LinearLayout with layout_weight="1" on the left and right view and 0 on the middle view. That pushes both icons off screen.

like image 476
Comtaler Avatar asked May 21 '15 00:05

Comtaler


2 Answers

Here is what I have done to achieve what I want:

I added layout_weight="1" to the middle TextView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">

    <TextView
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="left"/>

    <WrapWidthTextView
        android:id="@+id/middle"
        android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#D0E198"
        android:layout_weight="1"/>

    <TextView
        android:id="@+id/right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="right"/>
</LinearLayout>

However, when the middle text is short, it will still occupy the entire empty middle space and pushes the right TextView all the way to the right. I have to subclass TextView:

public class WrapWidthTextView
  extends TextView {

    // constructors here

    @Override protected void onMeasure (final int widthMeasureSpec, final int heightMeasureSpec) {
        super.onMeasure (widthMeasureSpec, heightMeasureSpec);

        Layout layout = getLayout ();
        if (layout != null) {
            int width = (int) Math.ceil (getMaxLineWidth (layout))
                        + getCompoundPaddingLeft () + getCompoundPaddingRight ();
            int height = getMeasuredHeight ();
            setMeasuredDimension (width, height);
        }
    }

    private float getMaxLineWidth (Layout layout) {
        float max_width = 0.0f;
        int lines = layout.getLineCount ();
        for (int i = 0; i < lines; i++) {
            if (layout.getLineWidth (i) > max_width) {
                max_width = layout.getLineWidth (i);
            }
        }
        return max_width;
    }
}

With WrapWidthTextView, when the text is short, it will shrink the view to fit the text.

And that solved my problem. I hope this will help others as well.

like image 196
Comtaler Avatar answered Sep 16 '22 17:09

Comtaler


Use the first layout, but add weighting to your middle textview.

Example:

 <TextView
        android:id="@+id/middle"
        android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:background="#D0E198"/>

Make sure to use 0dp as your width!

Note: This answer is if you want the icon to be right aligned. Which, I'm not sure that's what you need.

like image 23
Evan Bashir Avatar answered Sep 20 '22 17:09

Evan Bashir