3

I'm looking for the best way to meet this requirement. I apologize if it's been answered elsewhere, I can't find a solution to what seems like an easy problem.

You have a line of text in a list that looks something like this:

Title of the item - (5 items)

If the title of the item gets to be too long, then it wraps, which is expected. However, it shouldn't wrap between the "5" and the "items". If it needs to wrap, then the whole "(5 items)" should wrap to the next line. And the text of the title should ellipse.

I can't seem to find a way to create a layout that will work for this.

gnunaes
  • 186
  • 1
  • 9

4 Answers4

1

This may help. You can define which part of the text is going to be truncated by using the android:ellipsize attribute.

In your case, as per the linked answer, I would use android:ellipsize="middle" or android:ellipsize="marquee", which makes the text slide to be read.

While this does not actually answers your requirements (number of items automatically going to line two) I think it might be a better solution.

See official info here.


The other thing that comes to my mind is using two different TextViews, one for title and another one (right-aligned?) for item counts. I would give android:ellipsize="end" to the first and android:layout_width="wrap_content" to the latter.


Also you could go for a count TextView below the title, that gets appended to the title if there's enough room.

<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="wrap_content"
    android:id="@+id/container"
    android:orientation="vertical" >

    <TextView android:id="@+id/text1"
        android:text="a very very very long title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end" />


    <TextView android:id="@+id/text2"
        android:text="(5 items)"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

And in your code you can check for width:

View container = findViewById(R.id.container);
TextView tv1 = (TextView) findViewById(R.id.text1);
TextView tv2 = (TextView) findViewById(R.id.text2);


String HEADER = tv1.getText();
String COUNT = tv2.getText();

int widthHeader = tv1.getWidth();
int widthCount = tv1.getWidth();
int widthAvailable = container.getWidth();

if (widthAvailable - widthHeader > widthCount) {
    tv1.setText(HEADER + " - " + COUNT);
    tv2.setText("");
}
Community
  • 1
  • 1
natario
  • 24,954
  • 17
  • 88
  • 158
  • I agree that there is a better solution than doing it the way presented in my question. I've given several other options to the customer, but they've given some pushback on wanting it the way stated. Before I go back to them with "can't be done" I was hoping for a solution that fits with what they want. – gnunaes Jan 20 '15 at 14:23
1

The TextUtils classs has as method called ellipsize

public static CharSequence ellipsize (CharSequence text, TextPaint p, float avail, TextUtils.TruncateAt where) Added in API level 1

Returns the original text if it fits in the specified width given the properties of the specified Paint, or, if it does not fit, a truncated copy with ellipsis character added at the specified edge or center.

Here is how we can use it. Lets assume "Title of the item - (5 items)" is fullText, (5 items) is suffix, textView is your text view containing the text.

String ellipsizedText = TextUtils.ellipsize(fullText, textView.getPaint(), fullTexViewtWidth ,TextUtils.TruncateAt.END);

Now either the text will be ellipsized or it won't. We can check this by checking for the presence of suffix in the ellipsizedText. If it is ellipsized (suffix is removed), we should call the ellipsize function again but this time with reduced width since we want to preserve a space for our suffix string and remove suffix since we are adding it separately. So, the new call will be

ellipsizedText = TextUtils.ellipsize(removedSuffixText, textView.getPaint(), reducedWidth ,TextUtils.TruncateAt.END);

finally we set the text of the textView as ellipsizedText+suffix;

Few values we need to find out

  1. fullTexViewtWidth - This can be tricky since we have not specified specific width for the text view. suppose we set the width as match parent then we can achieve it via view tree observer. Follow the answers here
  2. reducedWidth - This is even more tricky. To calculate this we need to find the width occupied by suffix and subtract it from fullTexViewtWidth. This answer explains how to find width occupied by suffix

    final float densityMultiplier = getContext().getResources().getDisplayMetrics().density; final float scaledPx = 20 * densityMultiplier; paint.setTextSize(scaledPx); final float size = paint.measureText("sample text");

I am afraid this will only work when maxLines is 1 and width is set to matchparent for textView.

Community
  • 1
  • 1
Dhir Pratap
  • 1,188
  • 11
  • 14
  • 1
    After checking if the text is ellipsized you could replace " - " with "\n" and set the number of lines in your textview to 2. If it isn't ellipsized then just leave it to singleLine="true" with the original test. – David Corsalini Jan 22 '15 at 14:05
0

What i can understand from your question is that

1) It does not matter how long the title text is,it can wrap according to its length.

2) Your text "(5 items)" should not break, it should stays together. What ever
   is the length of your TITLE.

If above 2 points are correct.Then the simple solution is this

 Just replace your String "(5 items)"

with

 String "(5&#160;items)"

Note:

Here, '&#160' is character code of 'SPACE'. This bind's your string as one 
String and stays together.

Hope this resolves your problem.

A.R.
  • 2,631
  • 1
  • 19
  • 22
  • Sorry if i misunderstood your question and please let me know about this. – A.R. Jan 26 '15 at 18:27
  • Thanks for trying, but if the title is too long it should ellipsize and only fit on one line. If it does do this, then the (5 items) part should wrap to the next line. – gnunaes Jan 27 '15 at 14:32
0

Have you tried a relative layout with two textViews, one for title and other for "label" ? Use Relative layout to left of:

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/container" >

<TextView android:id="@+id/text1"
    android:text="a very very very long title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:toLeftOf="@+id/label" />


<TextView android:id="@+id/label"
    android:text="(5 items)"
    android:singleLine="true"
    android:layout_alignParentRight="true" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

You can use linearLayout weight too this will make the text always fit to a proportion (80% for title, and 20% for label in this example):

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weight_sum="100"
android:orientation="horizontal"
android:id="@+id/container" >

<TextView android:id="@+id/text1"
    android:weight="80"
    android:text="a very very very long title"
    android:layout_width="0dp"
    android:layout_height="wrap_content" />


<TextView android:id="@+id/label"
    android:text="(5 items)"
    android:singleLine="true"
    android:weight="20"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

</LinearLayout>
Renato Probst
  • 5,914
  • 2
  • 42
  • 45