Приоритет усечения Android TextView или сопротивление сжатию [дубликаты]

На этот вопрос уже есть ответ здесь:

Расширяйте TextView с помощью wrap_content, пока соседний вид не достигнет конца родительского 6 ответов

Я выкладываю 3 вида по горизонтали на экране (изображение фиксированного размера и 2 однострочных текста:leftTextView а такжеrightTextView) и я пытаюсь получитьrightTextView обнять противleftTextView, но в случае, если ширина обеих меток превысит размер экрана, обрежьтеleftTextiew.

Пример желаемой функциональности:

|img|leftText|rightText|                ||(end of screen)
|img|leftTextMedium|rightText|          ||
|img|leftTextTooLongSoTrunc...|rightText||

Что на самом деле происходит:

|img|leftText|rightText|                ||(end of screen)
|img|leftTextPrettyLongButNotHuge|rightT||
|img|leftTextWhichIsIncrediblyLongBlahBl||

В настоящее время, если размер обоих текстовых представлений превышает ширину представления,rightTextView заканчивает тем, что был раздавлен, чтобы освободить место, хотя я установилandroid:ellipsize="end" наleftTextView.

Есть ли способ сделатьleftTextView иметь "приоритет усечения", который говорит, что должен усечь, если это заставит другие представления не соответствовать? Или на другой стороне, могу ли я установитьrightTextView иметь «сопротивление сжатию», чтобы он не был сжат, чтобы освободить место дляleftTextView? Вот пример моего XML:

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

    <ImageView
        android:id="@+id/fixedWidthImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:id="@+id/leftTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toEndOf="@+id/fixedWidthImage"
        android:layout_toRightOf="@id/fixedWidthImage"
        android:maxLines="1"
        android:textSize="18sp"
        android:ellipsize="end" />

    <TextView
        android:id="@+id/rightTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toEndOf="@+id/leftTextView"
        android:layout_toRightOf="@+id/leftTextView"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:maxLines="1"
        android:textSize="12sp" />

</RelativeLayout>

Вещи, которые я пробовал:

вleftTextView, добавитьtoStartOf / toLeftOf rightTextView (вылетает приложение)

Вместо выравниванияrightTextView до конца / справа отleftTextViewпереверните и выровняйтеleftTextView к началу / слева отrightTextView, Это приводит кrightTextView привязка к концу экрана, а не прямо справа отleftTextView, Пример того, как это выглядит:

|img|leftText                 |rightText||
|img|leftTextMedium           |rightText||
|img|leftTextTooLongSoTrunc...|rightText||

Даже если я поставлюandroid:minWidth="25dp" просто чтобы обеспечить хотя бычасть изrightTextView является видимым (что я не хочу делать, потому что эта длина текста является переменной), он все равно сжимает ширину, чтобы освободить место дляleftTextView.

вЭмануэль Меклинответ, я попытался завернуть вLinearLayout и установив вес наleftTextView, Результат был визуально идентичен тому, что я пробовал в # 2.
 Stonz205 окт. 2016 г., 18:39
В мою защиту дублирующей маркировки у этого другого вопроса не было ответа в то время, когда я задавал свой. Кроме того, его название ужасно, поэтому, вероятно, я не осознавал, что он вообще существует.

Ответы на вопрос(4)

Просто используйтеandroid:maxWidth свойство слева от вас textView. Таким образом, ваш левый взгляд никогда не будет превышать этот предел. и всегда будет место для вашего правильного взгляда.

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

    <ImageView
        android:id="@+id/fixedWidthImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/leftTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/fixedWidthImage"
        android:layout_toRightOf="@+id/fixedWidthImage"
        android:ellipsize="end"
        android:lines="1"
        android:maxWidth="250dp"
        android:text="This is a Long left Text which never ends and You'll be tired after reading this long stuff.. blah blah... " />

    <TextView
        android:id="@+id/rightTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/leftTextView"
        android:layout_toRightOf="@+id/leftTextView"
        android:ellipsize="end"
        android:lines="1"
        android:text="Right Text" />

</RelativeLayout>

Однако ограничение решения состоит в том, что вы должны указывать фиксированное значение в свойстве maxWidth. Таким образом, он будет отображаться по-разному на экране другого размера. Хотя в большинстве случаев вы не столкнетесь с проблемой.

Также для отображения длинного textView в одной строкеandroid:ellipsize="marquee" хороший вариант. Как это будет прокручивать ваш взгляд по горизонтали. Но не забудьте написать этоtextView.setSelected(true) в вашем коде, чтобы заставить его работать.подробность

 Stonz215 авг. 2016 г., 19:40
В Android с таким большим несоответствием размеров экрана (плюс книжный и альбомный) фиксированная ширина - определенно нежелательный подход.
 Shaishav Jogani16 авг. 2016 г., 07:13
Я уже говорил, что это будет работать, когда вы знаете фиксированный размер изображения по ширине. В противном случае вы можете сделать это программно, как предложено @ whizzle.
Решение Вопроса

Вы можете заархивировать этот макетTableLayout а такжеshrinkColumns приписывать.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <!-- Row 1 -->
    <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:shrinkColumns="1">

        <TableRow
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical">

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@mipmap/ic_launcher"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:text="leftText"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="none"
                    android:text="rightText"/>
        </TableRow>

    </TableLayout>


    <!-- Row 2 -->
    <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:shrinkColumns="1">

        <TableRow
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical">

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@mipmap/ic_launcher"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:text="leftTextPrettyLongButNotHuge"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="none"
                    android:text="rightText"/>
        </TableRow>

    </TableLayout>

    <!-- Row 3 -->
    <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:shrinkColumns="1">

        <TableRow
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical">

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@mipmap/ic_launcher"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:text="leftTextWhichIsIncrediblyLongBlahBlahBlahBlah"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="4dp"
                    android:maxLines="1"
                    android:ellipsize="none"
                    android:text="rightText"/>
        </TableRow>

    </TableLayout>

</LinearLayout>

 jmarkstar04 июн. 2019 г., 23:24
Как я могу сделать это, используя ConstraintLayout?
 woxingxiao17 мая 2018 г., 11:50
Задаватьandroid:shrinkColumns="0" работает нормально.
 Vlad25 июл. 2017 г., 20:13
Можно ли это сделать для вертикальных макетов? Мне нужно, чтобы элементы в TableRow были выровнены по вертикали и установлены android: shrinkColumns = "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:orientation="horizontal">

    <ImageView
        android:id="@+id/fixedWidthImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@drawable/ic_launcher_pro" />

    <TextView
        android:id="@+id/leftTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center_vertical|left"
        android:ellipsize="marquee"
        android:lines="1"
        android:text="This is a very long text, and now even longer" />

    <TextView
        android:id="@+id/rightTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|left"
        android:lines="1"
        android:text="This is also quite long" />

</LinearLayout>

Андроид: layout_weight = "1" делает "трюк" здесь. Документация не совсем ясна по этому вопросу, хотя:

Например, если есть три текстовых поля и два из них объявляют вес 1, а другому не присвоен вес, третье текстовое поле без веса не будет расти и будет занимать только область, требуемую его содержимым.

(https://developer.android.com/guide/topics/ui/layout/linear.html#Weight)

Он не раскрывает случай, когда не хватает места для заполнения, но недостаточно места для всех видов. Одна интерпретация упомянутого фрагмента документации будет состоять в том, что поле без веса (в данном случае rightTextView) будет занимать область, требуемую его содержимым, в то время как поле с весом (в данном случае leftTextView) будет «расти» (как в отрицательном значении). рост) и это именно то, что происходит.

 AJW27 мар. 2019 г., 03:47
@ Эмануэль Меклин, что если я использую RelativeLayout, а не LinearLayout?
 Stonz212 авг. 2016 г., 19:48
Хотя вес учитывает «отрицательный рост», который вы упоминаете, он также расширяет поле, чтобы заполнить ширину, когда это не нужно. Это заканчиваетсяrightTextView быть закрепленным справа / в конце родительского представления. Функционально это выглядит так же, как и в # 2 из того, что я пробовал в этом вопросе.

Я думаю, что вам нужно будет сделать собственный макет. Это хорошо работает для примера, который я сделал, и отвечает всем требованиям, которые вы опубликовали выше, но вам нужно будет добавить немного математики в код для учета layout_margins и padding.

Основная идея того, что здесь происходит, заключается в том, что я делю на подклассы LinearLayout, и на проходе onMeasure я проверяю, чтобы убедиться, что в правильном представлении есть возможность занять как можно больше места. Обратите внимание, что мне нужно пересмотреть правильный вид, а не просто получить измеренную ширину, потому что линейное расположение не даст ему достаточно места. После того, как вы определите, сколько места занимает нужный вид, проверьте, занимает ли средний вид (называемый leftView ... извините) больше места, чем вы хотите. Если это так, просто дайте ему место, которое осталось.

Исходя из ваших требований того, что он находится в RecyclerView ... Я знаю, что вы сказали, что хотите чисто xml-решение, но вы получите лучшую производительность, если вы решите его в коде как xml 1. Это может быть невозможно, а 2. будет требует больше вычислений, чем просто делать это самостоятельно.

public class CustomLinearLayout extends LinearLayout {

private View child0;
private TextView leftView, rightView;
public CustomLinearLayout(Context context) {
    super(context);
}

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

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

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (rightView == null) {
        child0 = getChildAt(0);
        leftView = (TextView)getChildAt(1);
        rightView = (TextView) getChildAt(2);
    }

    int spec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
    rightView.measure(spec, spec);

    int remaining = getMeasuredWidth() - child0.getMeasuredWidth() - rightView.getMeasuredWidth();
    if (leftView.getMeasuredWidth() > remaining) {
        int specW = MeasureSpec.makeMeasureSpec(remaining, MeasureSpec.AT_MOST);
        int specH = MeasureSpec.makeMeasureSpec(leftView.getMeasuredHeight(), MeasureSpec.EXACTLY);
        leftView.measure(specW, specH);
    }
}

Макет XML

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.joshua.myapplication.MainActivity">

<com.example.joshua.myapplication.CustomLinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <ImageView
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:background="#FF0000"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:textSize="18sp"
        android:text="My Left View With Really Really Long Text That should fill the screen"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:textSize="18sp"
        android:text="My Right View"
        />
</com.example.joshua.myapplication.CustomLinearLayout>

<com.example.joshua.myapplication.CustomLinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_marginTop="20dp">
    <ImageView
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:background="#FF0000"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:textSize="18sp"
        android:text="My Left View with short text"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:textSize="18sp"
        android:text="My Right View"
        />
</com.example.joshua.myapplication.CustomLinearLayout>
</LinearLayout>

 Stonz216 авг. 2016 г., 20:08
Спасибо за ответ - я дал ему повод, и он отлично работает, но подход nshmura также работает, но только в XML и не опирается на подклассы.

Ваш ответ на вопрос