Два TextViews рядом, только один для многоточия? - PullRequest
64 голосов
/ 24 сентября 2010

Я хочу, чтобы два элемента TextView появлялись рядом (в элементе списка), один выровненный по левому краю, один по правому. Что-то вроде:

|<TextView>               <TextView>|

(| представляет конечности экрана)

Тем не менее, TextView слева может иметь слишком длинный контент, чтобы поместиться на экране. В этом случае я хочу, чтобы он имел размер эллипса, но все еще показывает полное право TextView. Что-то вроде:

|This is a lot of conte...<TextView>|

У меня были многочисленные попытки сделать это, используя LinearLayout и RelativeLayout, и единственное решение, которое я нашел, - это использовать RelativeLayout и поставить marginRight слева TextView большой достаточно, чтобы очистить право TextView. Однако, как вы можете себе представить, это не оптимально.

Есть ли другие решения?

Финал, LinearLayout решение:

<LinearLayout
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:orientation="horizontal"
    >
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_weight="1"
        android:ellipsize="end"
        android:inputType="text"
        />
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_weight="0"
        android:layout_gravity="right"
        android:inputType="text"
        />
</LinearLayout>

Старый, TableLayout Решение:

<TableLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="1"
    android:shrinkColumns="0"
    >
    <TableRow>
        <TextView android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            />
        <TextView android:id="@+id/date"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:singleLine="true"
            android:ellipsize="none"
            android:gravity="right"
            />
    </TableRow>
</TableLayout>

Ответы [ 5 ]

19 голосов
/ 24 сентября 2010

Просто идея, почему бы вам сначала не объявить в макете XML текстовое представление справа и не установить его ширину в качестве содержимого переноса, android:layout_alignParentRight="true" и android:gravity="right". Затем объявите текстовое представление слева, установите его ширину в качестве родительского заполнения, android:layout__toLeftOf = {идентификатор текстового просмотра справа}, имеющего RelativeView в качестве корневого представления.

Объявляя сначала правое текстовое представление, его необходимая ширина будет вычислена первой и займет вид, в то время как текстовое представление слева будет занимать оставшееся пространство вида.

Я до сих пор не пробовал это, хотя это может дать вам некоторое представление.

[Обновление]

Я попытался создать макет ресурса xml ... и это как-то работает ...

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <TextView 
    android:id="@+id/right"
    android:layout_alignParentRight="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="right"
    android:text="right"
    >
  </TextView>
  <TextView 
    android:id="@+id/left"
    android:layout_alignParentLeft="true"
    android:layout_toLeftOf="@id/right"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:lines="1"
    android:singleLine="true"
    android:maxLines="1"
    android:text="too looooooooooong ofskgjo sdogj sdkogjdfgds dskjgdsko jgleft"
    >
  </TextView>
</RelativeLayout>
17 голосов
/ 29 ноября 2012

Ответ LinearLayout работал для меня с этой же проблемой.Размещено как отдельный ответ, потому что неясно, что сработало и не сработало для аскера.

Одно отличие.TableLayout был менее идеален для меня, потому что у меня было две строки данных, и я хотел, чтобы нижняя строка работала так, как описывает этот вопрос, и верхняя строка, чтобы охватить область.На этот вопрос ответили в другом SO-вопросе: Colspan в TableLayout , но LinearLayout был проще.

Хотя правильная ширина заняла у меня немного времени.Я включил настройку Android lint с использованием 0dp width для элемента масштабирования для производительности.

<LinearLayout
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:orientation="horizontal"
    >
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:ellipsize="end"
        android:inputType="text"
        />
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_weight="0"
        android:layout_gravity="right"
        android:inputType="text"
        />
</LinearLayout>
15 голосов
/ 24 сентября 2010

Используйте TableLayout и поместите оба TextView в строку таблицы, попробуйте.Я не пробовал

1 голос
/ 10 октября 2015

Есть много ответов на этот и практически эквивалентные, дублирующие вопросы по SO.Предлагаемые подходы обычно работают, вроде.Положите его в LinearLayout, оберните все в дополнительные RelativeLayout, используйте TableLayout;кажется, что все это решает проблему для более простого макета, но если вам нужны эти два TextView внутри чего-то более сложного, или же один и тот же макет будет повторно использован, например, RecyclerView, все очень быстро сломается.*

Единственное найденное мной решение, которое действительно работает все время, независимо от того, в какой макет вы его поместите, - это пользовательский макет.Его очень просто реализовать, и, будучи настолько скудным, насколько это возможно, он будет сохранять макет достаточно плоским, его легко поддерживать, поэтому в долгосрочной перспективе я считаю это лучшим решением проблемы.

public class TwoTextLayout extends ViewGroup {

  public TwoTextLayout(Context context) {
    super(context);
  }

  public TwoTextLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public TwoTextLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = getChildCount();
    if (count != 2)
      throw new IllegalStateException("TwoTextLayout needs exactly two children");

    int childLeft = this.getPaddingLeft();
    int childTop = this.getPaddingTop();
    int childRight = this.getMeasuredWidth() - this.getPaddingRight();
    int childBottom = this.getMeasuredHeight() - this.getPaddingBottom();
    int childWidth = childRight - childLeft;
    int childHeight = childBottom - childTop;

    View text1View = getChildAt(0);
    text1View.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
    int text1Width = text1View.getMeasuredWidth();
    int text1Height = text1View.getMeasuredHeight();

    View text2View = getChildAt(1);
    text2View.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
    int text2Width = text2View.getMeasuredWidth();
    int text2Height = text2View.getMeasuredHeight();

    if (text1Width + text2Width > childRight)
      text1Width = childRight - text2Width;

    text1View.layout(childLeft, childTop, childLeft + text1Width, childTop + text1Height);
    text2View.layout(childLeft + text1Width, childTop, childLeft + text1Width + text2Width, childTop + text2Height);
  }
}

Реализация не может быть проще, она просто измеряет два текста (или вообще любые другие дочерние представления) и, если их объединенная ширина превышает ширину макета, уменьшает ширину первого вида.

И если вам нужны модификации, например.чтобы выровнять второй текст с базовой линией первого, вы также можете легко решить эту проблему:

text2View.layout(childLeft + text1Width, childTop + text1Height - text2Height, childLeft + text1Width + text2Width, childTop + text1Height);

или любое другое решение, такое как сжатие второго вида относительно первого, выравнивание вправо,и т.д.

0 голосов
/ 24 сентября 2010

Почему бы вам не поставить левое поле в правое TextView?Я использую этот подход для

|<TextView>       <ImageButton>|

, и он работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...