41

我的问题与How to get a layout where one text can grow and ellipsize, but not gove up the other elements on the layout非常相似,但请阅读下面为什么我不能使用那里提出的 TableLayouts 。

我正在尝试创建一个基本上如下所示的列表视图行:

| 文本视图 | 查看 1 | 查看 2 |

所有视图都包含可变宽度元素。TextView 设置了 ellipsize="end" 。视图 1 应对齐 TextView 的左侧,而视图 2 应对齐屏幕的右侧。因此,通常情况下,视图 1 和视图 2 之间会有空格。随着 TextView 中的文本变长,TextView 应该会增长,将视图 1 向右推,直到没有更多的空格。然后,ellipsize 应该开始,在 TextView 中剪切文本并在末尾附加一个省略号(“...”)。

所以,结果应该是这样的:

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

我试过了:

  • TableLayouts,但它们似乎使某些设备上的滚动非常缓慢。
  • RelativeLayouts,但我要么有重叠的视图,要么 view1 或 view2 完全消失了。
  • GridLayouts,但 TextView 总是会增长,直到它占据屏幕的整个宽度,从而将 view1 和 view2 推出屏幕。

这是我试过的 GridLayout:

<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 和 View 2 并不是真正的 TextView,我只是在示例中使用它们来简化事情。

有没有办法在不使用 TableLayouts 的情况下实现这一点?

编辑: 根据要求,这是我用RelativeLayout 解决这个问题的尝试。在这种情况下,TextView 占据了屏幕的整个宽度,因此 view1 和 view2 都不可见。

<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>
4

14 回答 14

21

我似乎找到了一个潜在的解决方案来防止 GridLayout 中的 TextView 无限制地增长并推出其他视图。不确定这是否已经记录在案。

您需要使用填充 layout_gravity 并在需要椭圆化的长 TextView 上设置任意 layout_width 或宽度。

android:layout_gravity="fill"
android:layout_width="1dp"

适用于 GridLayout 和 android.support.v7.widget.GridLayout

于 2015-12-04T23:33:08.653 回答
9

我是 LinearLayouts 的忠实粉丝,所以这是我使用这些的建议:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            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_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="(view1)" />
    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="(view2)" />
</LinearLayout>
于 2013-07-15T14:49:54.413 回答
3

我认为您应该为您的目的创建自定义布局。我不知道如何仅使用默认布局/视图来做到这一点,并使其适用于所有情况。

于 2013-07-23T10:30:04.563 回答
3

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] |
+----------------------------------------+
于 2013-07-23T06:40:30.277 回答
3

对我有用的技巧是使用 maxWidth 来限制第一个视图的宽度。你需要用Java来做,这里是基本逻辑:

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

不漂亮,但它有效。

于 2015-06-25T01:12:46.017 回答
2

我认为只有一个可以解决的布局小问题,将 view3 锚定到右侧并从那里开始强制视图具有分隔区域(因此能够正确设置椭圆):

<?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>

希望这可以帮助...

问候!

于 2013-07-24T18:52:17.490 回答
0

尝试这个

<?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:baselineAligned="false"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
        <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="left"
             android:text="(view1)"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
        <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="right"
             android:text="(view2)"/>
    </LinearLayout>

</LinearLayout>

目前,所有视图都居中。您可以更改android:gravity属性以满足您的需求。例如,您可能希望view1左右对齐,view2在这种情况下,最后两个LinearLayouts 看起来像(左右分别有 5dp 边距):

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center|right">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginRight="5dp"
        android:text="(view1)"/>
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center|left">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginLeft="5dp"
        android:text="(view2)"/>
</LinearLayout>
于 2013-07-15T15:21:31.783 回答
0

尝试使用布局权重

   <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>

在这里,我采用了表格行,其中布局权重总和为 10,这意味着它是其父级的 100% 宽度。并且在其所有子视图中,我已将宽度设置为 0Dp,并将权重设置为 1 或 2。这样它将占用总数 10 的百分比。因此布局将相应调整屏幕,并且不会有重叠的问题.

如果我对您的理解正确,那么这就是您想要的答案。

希望能帮助到你!

于 2013-07-24T09:56:11.187 回答
0

我找到了案例 2(带有长文本的案例)的解决方案:

<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>

真正的问题是案例一,我没有为此尝试很多东西。我希望它有所帮助(如果我有更多的空闲时间,我会努力实现第一个!)。

于 2013-07-18T08:57:37.593 回答
0

如果右侧的视图被设计的文本推倒,您不妨使用 ListView 而不是 GridView。

您只需要将列表项布局的基础设置为 RelativeLayout,并设置如下规则:

  1. 您可以将右侧的两个视图设置为 alignParentRight(使用 android:layout_alignParentLeft="true"),但请确保第一个视图保持在第二个视图的左侧,以便在视图伸展时将自身推向左侧。

  2. 您可以使左侧的 TextView 与左侧对齐,但保持在第一个视图的左侧(使用 android:layout_toLeftOf="@+id/viewId"),这样它就不会与视图重叠。

于 2013-07-22T23:16:47.180 回答
0

我对网格布局有同样的问题。我所做的是为文本视图提供了一个固定的宽度,并layout_columnWeight为每个文本视图提供了属性,然后问题得到了解决,希望它有所帮助......

           <TextView
                android:id="@+id/txtName"
                style="@style/MyDetailTitle"
                android:layout_width="@dimen/detail_length"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                app:layout_column="3"
                app:layout_columnWeight="1"
                app:layout_gravity="start"
                app:layout_row="1" />
于 2016-02-17T08:04:54.770 回答
0

GridLayout 就像 Android 上的其他东西一样:设计上存在缺陷。

您将需要一个自定义布局,以下示例将允许您布局如下内容:

    [      label | short text     | very long label | short text     ]

    [ long label | very very very |           label | very long text ] 
    [            | long text      |                 |                ]



import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;


public class TwoColumsGridLayout extends ViewGroup {
    private final List<List<View>> rows;
    private int rowCount = 0;
    private int firstColumWidth;
    private int secondColumWidth;
    private int thirdColumWidth;
    private int fourthColumnWidth;
    private final List<Integer> rowHeights = new ArrayList<>();
    private final List<List<Integer>> cellHeights = new ArrayList<>();
    private final List<Integer> firstCellsWidths = new ArrayList<>(4);
    private final List<Integer> thirdCellsWidths = new ArrayList<>(4);

    public TwoColumsGridLayout(Context context, int rowCount) {
        super(context);
        rows = new ArrayList<>(rowCount);
    }


    public void add(Context ctx, TextView l1, View t1, TextView l2, View t2) {
        final List<View> row = new ArrayList<>(4);
        row.add(l1);
        row.add(t1);
        row.add(l2);
        row.add(t2);
        rows.add(row);
        this.addView(l1);
        this.addView(t1);
        if (l2 != null)
            this.addView(l2);
        if (t2 != null)
            this.addView(t2);
        this.rowCount++;
    }

    public int getRowCount() {
        return rowCount;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int curLeft = 0;
        int curBottom;
        int curRight;
        int curTop = 0;
        int i = 0;
        for (List<View> row : rows) {
            final int rowHeight = this.rowHeights.get(i);
            final List<Integer> rowCellHeights = this.cellHeights.get(i);
            final View v0 = row.get(0);
            curLeft = 0;
            curRight = curLeft + this.firstColumWidth;
            if (v0 != null) {
                curBottom = curTop + rowCellHeights.get(0);
                // Right align
                v0.layout(curLeft + this.firstColumWidth - this.firstCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
            }
            //
            final View v1 = row.get(1);
            curLeft += this.firstColumWidth;

            curRight = curLeft + this.secondColumWidth;
            if (v1 != null) {
                curBottom = curTop + rowCellHeights.get(1);
                v1.layout(curLeft, curTop, curRight, curBottom);
            }
            //
            final View v2 = row.get(2);
            curLeft += this.secondColumWidth;
            curRight = curLeft + this.thirdColumWidth;
            if (v2 != null) {
                curBottom = curTop + rowCellHeights.get(2);
                // Right align
                v2.layout(curLeft + this.thirdColumWidth - this.thirdCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
            }
            //
            final View v3 = row.get(3);
            curLeft += this.thirdColumWidth;
            curRight = curLeft + this.fourthColumnWidth;
            if (v3 != null) {
                curBottom = curTop + rowCellHeights.get(3);
                v3.layout(curLeft, curTop, curRight, curBottom);
            }
            curTop += rowHeight;
            i++;
        }

    } 

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        // Compute first column width
        firstColumWidth = 0;
        for (List<View> row : rows) {
            final View v = row.get(0);
            if (v != null) {
                v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                measureChild(v, widthMeasureSpec, heightMeasureSpec);
                final int w = v.getMeasuredWidth();
                if (firstColumWidth < w) {
                    firstColumWidth = w;
                }
            }
        }
        // Compute third column width
        thirdColumWidth = 0;
        for (List<View> row : rows) {
            final View v = row.get(2);
            if (v != null) {
                v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                measureChild(v, widthMeasureSpec, heightMeasureSpec);
                final int w = v.getMeasuredWidth();
                if (thirdColumWidth < w) {
                    thirdColumWidth = w;
                }
            }
        }
        secondColumWidth = (parentWidth - firstColumWidth - thirdColumWidth) / 2;
        fourthColumnWidth = parentWidth - firstColumWidth - secondColumWidth - thirdColumWidth;
        // Clear
        this.rowHeights.clear();
        this.cellHeights.clear();
        this.firstCellsWidths.clear();
        this.thirdCellsWidths.clear();
        // Compute heights
        int height = 0;
        for (List<View> row : rows) {
            final ArrayList<Integer> rowCellHeights = new ArrayList<>(4);
            cellHeights.add(rowCellHeights);
            int rowHeight = 0;
            // First column
            final View v0 = row.get(0);
            if (v0 != null) {
                int h = v0.getMeasuredHeight();
                this.firstCellsWidths.add(v0.getMeasuredWidth());
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            } else {
                this.firstCellsWidths.add(0);
            }
            // Second column
            final View v1 = row.get(1);
            if (v1 != null) {
                v1.setLayoutParams(new ViewGroup.LayoutParams(secondColumWidth, LayoutParams.WRAP_CONTENT));
                measureChild(v1, widthMeasureSpec, heightMeasureSpec);
                int h = v1.getMeasuredHeight();
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            }
            // Third column
            final View v2 = row.get(2);
            if (v2 != null) {
                int h = v2.getMeasuredHeight();
                this.thirdCellsWidths.add(v2.getMeasuredWidth());
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            } else {
                this.thirdCellsWidths.add(0);
            }
            // Fourth column
            final View v3 = row.get(3);
            if (v3 != null) {
                v3.setLayoutParams(new ViewGroup.LayoutParams(fourthColumnWidth, LayoutParams.WRAP_CONTENT));
                measureChild(v3, widthMeasureSpec, heightMeasureSpec);
                int h = v3.getMeasuredHeight();
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            }
            height += rowHeight;
            this.rowHeights.add(rowHeight);

        }
        setMeasuredDimension(parentWidth, height);
    }
}

玩得开心。

于 2018-01-08T20:33:05.713 回答
0

TableLayout 将给出预期的行为。正如问题的作者提到的那样,可能会导致性能问题,但在简单的布局中效果很好。如果该行是可重复且可滚动的,请考虑改用 gridview

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

        <TextView/>

        <View1/>

        <View2/>
    </TableRow>
</TableLayout>
于 2018-08-29T04:25:55.977 回答
0

首先,您必须将 [view 2] 布局到父权;

同样,您引用了对最后两个布局的引用!

<Relativelayout android:layout_width="match_parent"
            android:layout_height="wrap_content"
      <TextView
        android:id="@+id/view2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
       />

      <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeft="@id/view2"
        android:gravity="left">

        <TextView
            android:id="@+id/shortORlongtTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/view1"
            android:ellipsize="end"
            android:maxLines="1"
            android:textSize="18dp"/>

        <TextView
            android:id="@+id/view1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
           />
    </RelativeLayout>

于 2015-12-10T03:29:10.777 回答