Ответ 1
Используйте TableLayout и поместите оба TextView в строку таблицы, попробуйте. Я не пробовал
Я хочу, чтобы два элемента TextView
отображались бок о бок (в элементе списка), один был выровнен слева, один - вправо. Что-то вроде:
|<TextView> <TextView>|
(|
представляют крайности экрана)
Тем не менее, TextView
слева может содержать слишком длинный контент, который будет помещаться на экране. В этом случае я хочу, чтобы он был эллипсисом, но все же отображал все правое TextView
. Что-то вроде:
|This is a lot of conte...<TextView>|
У меня было множество попыток, используя как LinearLayout
, так и RelativeLayout
, и единственным решением, которое я придумал, является использование RelativeLayout
и добавление marginRight
влево TextView
big достаточно, чтобы очистить право 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>
Используйте TableLayout и поместите оба TextView в строку таблицы, попробуйте. Я не пробовал
Просто идея, почему бы вам не объявить сначала в макете 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>
Ответ LinearLayout работал у меня с этой же проблемой. Добавлено как отдельный ответ, потому что было непонятно, что делали и не работали для искателя.
Одно отличие. TableLayout был менее идеальным для меня, потому что у меня было две строки данных, и я хотел, чтобы нижняя строка вела себя так, как описывает этот вопрос, и верхнюю строку для охвата области. На этот вопрос был дан ответ в другом вопросе SO: Colspan в TableLayout, но LinearLayout был проще.
Хотя получение ширины справа меня немного. Я включил настройку андроидного линта с использованием ширины 0dp
для элемента масштабирования для производительности.
<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>
Есть много ответов на этот и практически эквивалентные, повторяющиеся вопросы о 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);
Или любое другое решение, например, сокращение второго представления по отношению к первому, выравнивание вправо и т.д.
Почему бы вам не поместить левое поле в правый TextView? Я использую этот подход для
|<TextView> <ImageButton>|
и он работает.
Решение с ConstraintLayout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/leftText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintEnd_toStartOf="@id/rightText"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="This is a lot of content that should be cut" />
<TextView
android:id="@+id/rightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Right text" />
</androidx.constraintlayout.widget.ConstraintLayout>