Android TextView Truncation Priority or Compression Resistance [duplicate]

两盒软妹~` 提交于 2019-12-01 15:47:06

You can archive this layout by TableLayout and shrinkColumns attribute.

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

Here's what I do:

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

The android:layout_weight="1" does the "trick" here. The documentation isn't quite clear on this one though:

For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content.

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

It doesn't elaborate on the case in which there isn't space to fill but not enough space for all views. One interpretation of the mentioned piece of documentation would be that a field without weight (the rightTextView in this case) will occupy the area required by its content while a field with weight (the leftTextView in this case) will "grow" (as in negative growth) and that's exactly what happens.

I think you're going to need to make a custom layout. This works well for the sample I made and it meets all of the requirements you posted above, but you'll need to add a touch more math the code to account for layout_margins and padding.

The basic idea of what's going on here is I subclassed LinearLayout and in the onMeasure pass, I check to make sure that right view has the option to take up as much space as possible. Note that I have to remeasure the right view and not just get the measured width because linearlayout isn't going to give it enough space. Once you have how much room the right view takes up, check to see if the middle view (called leftView...sorry) is taking up more space than you want. If it does, just give it the space that's left over.

Based upon your requirements of it being in a RecyclerView... I know you said you wanted a pure xml solution, but you're going to get better performance if you tackle it in code as xml 1. may be impossible and 2. will require more computations than just doing it yourself directly.

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 layout

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

Shaishav Jogani

Just use android:maxWidth property to your left textView. So, your leftview will never exceed that limit. and there will be always space for your right view.

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

However, limitation with solution is you have to give fixed value in maxWidth property. So, it'll display different look on different screen size. Though, in most cases you'll not face issue.

Also, for displaying long textView in single line android:ellipsize="marquee" is good option. As it'll scroll your view horizontal. But don't forget to write this textView.setSelected(true) in your code to make it work. Detail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!