Textview with long text pushes out other views in

2019-01-31 17:19发布

My problem is very similar to How to get a layout where one text can grow and ellipsize, but not gobble up the other elements on the layout, but read on below why I can't use TableLayouts as proposed there.

I'm trying to create a listview row that basically looks like this:

| TextView | View 1 | View 2 |

All views contain variable width elements. The TextView has ellipsize="end" set. View 1 should align left of the TextView, while View 2 should align to the right of the screen. So, normally, there would be whitespace between View 1 and View 2. As the text in the TextView grows longer, the TextView should grow, pushing View 1 to the right until there is no more whitespace left. Then, ellipsize should kick in, cutting of the text in TextView and appending an ellipsis ("...") at the end.

So, the result should look something like this:

+----------------------------------------+
| short text [view1]             [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+

I've tried:

  • TableLayouts, but they seem to make scrolling extremely slow on some devices.
  • RelativeLayouts, but I either had overlapping views, or view1 or view2 disappeared completely.
  • GridLayouts, but the TextView always grows until it takes up the whole width of the screen, thus pushing view1 and view2 out of the screen.

This is the GridLayout I tried:

<GridLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:layout_gravity="left|fill_horizontal"
        android:ellipsize="end"
        android:singleLine="true"
        android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />

    <TextView
        android:layout_gravity="left"
        android:text="(view1)" />

    <TextView
        android:layout_gravity="right"
        android:text="(view2)" />
</GridLayout>

View 1 and View 2 are not really TextViews, I just used them in the example to simplify things.

Is there any way to achieve this without using TableLayouts?

EDIT: As requested, here is my attempt at solving this with a RelativeLayout. The TextView takes up the full width of the screen in this case, so neither view1 nor view2 are visible.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/rl0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:ellipsize="end"
        android:singleLine="true"
        android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />

    <TextView
        android:id="@+id/rl1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/rl0"
        android:layout_marginLeft="10dp"
        android:text="(view1)" />

    <TextView
        android:id="@+id/rl2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/rl1"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="10dp"
        android:text="(view2)" />
</RelativeLayout>

14条回答
可以哭但决不认输i
2楼-- · 2019-01-31 17:56

I will suggest you to play with layout_weight property of your widget

Example:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:orientation="horizontal"
    android:weightSum="10">

    <LinearLayout
       android:id="@+id/ll_twoViewContainer"
       android:layout_weight="8"
       android:layout_width="0dp"
       android:layout_height="wrap_content" 
       android:orientation="horizontal">

      <TextView
          android:id="@+id/rl0"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentLeft="true"
          android:layout_weight="1"
          android:ellipsize="end"
          android:singleLine="true"
          android:text="Long text" />

      <TextView
          android:id="@+id/rl1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginLeft="10dp"
          android:layout_toRightOf="@id/rl0"
          android:layout_weight="1"
          android:minWidth="120dp"
          android:text="(view1)" />

    </LinearLayout>
    <TextView
        android:id="@+id/rl2"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/rl1"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="10dp"
        android:text="(view2)" />
  </LinearLayout>

</LinearLayout>

finally your layout will look like as follow:

+----------------------------------------+
| short text [view1]             [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
查看更多
迷人小祖宗
3楼-- · 2019-01-31 17:59

I find my solution for the case number 2 (the one with a long text):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:weightSum="3" >

    <TextView
        android:id="@+id/rl0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:ellipsize="end"
        android:singleLine="true"
        android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />

    <TextView
        android:id="@+id/rl1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_weight="1"
        android:text="(view1)" />

    <TextView
        android:id="@+id/rl2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_weight="1"
        android:text="(view2)" />

</LinearLayout>

The real problem is case one, and i didn't try a lot of things for this. I hope it helps (and if i have more spare time, i will try to achieve first one!).

查看更多
姐就是有狂的资本
4楼-- · 2019-01-31 18:00

The trick which worked for me was to use maxWidth to restrict the width of the first view. You need to do it with Java, here is the basic logic:

firstView.setMaxWidth(parentView.getWidth() - view2.getWidth() - view1.getWidth() - padding * 2);

Not pretty, but it works.

查看更多
小情绪 Triste *
5楼-- · 2019-01-31 18:03

Try using Layout Weight

   <TableRow
        android:id="@+id/tableRow3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/tableRow2"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        android:weightSum="10"
        android:background="@android:color/black" >

        <TextView
            android:id="@+id/txtInningsTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center"
            android:text="0" 
            android:textColor="@android:color/white" />

        <TextView
            android:id="@+id/txtTeamOneTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2.5"
            android:gravity="center"
            android:text="0" 
            android:textColor="@android:color/white" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2" />

        <TextView
            android:id="@+id/txtTeamTwoTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2.5"
            android:gravity="center"
            android:text="0"
            android:textColor="@android:color/white"  />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2" />

        <TextView
            android:id="@+id/txtGrandTotal"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:text="0"
            android:textColor="@android:color/white"  />
    </TableRow>

Here i have taken table row in which there is layout weight sum which is of 10 means that it is 100% width of its parent. and in all its child views i have set width to 0Dp and given weight to 1 or 2. so that it will take up to that percent of total 10. so the layout will be adjusted accordingly screen and also there will be no issue of overlapping.

If i have understood you correctly then this is the answer you wanted.

Hope it Helps!

查看更多
欢心
6楼-- · 2019-01-31 18:04

TableLayout will give expected behavior. May cause performance issue as question's author mention, but works great with simple layout. If the row is repeatable and scrollable, consider use gridview instead

<TableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="1"
    android:shrinkColumns="0"
    >
    <TableRow>

        <TextView/>

        <View1/>

        <View2/>
    </TableRow>
</TableLayout>
查看更多
放荡不羁爱自由
7楼-- · 2019-01-31 18:06

I think there's just a small issue on the layout that could be solved, anchoring the view3 to the right and start from there to force the view to have a delimited area (hence being able to properly set the ellipse):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
<TextView
        android:id="@+id/rl3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="(view2)" />
<TextView
        android:id="@+id/rl2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/rl3"
        android:text="(view1)" />
<TextView
        android:id="@+id/rl1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:singleLine="true"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/rl2"
        android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
</RelativeLayout>

Hope this helps...

Regards!

查看更多
登录 后发表回答