22

I have an Android application layout which contains a multiline TextView. When the screen is in portrait orientation, the TextView can display a different length of text to when running in landscape mode. Also when running on a small screen, the TextView can display a different length of text to when running on a larger screen.

Is there any way I can check if the text fits or will be truncated? Or is there any way I can check if the TextView if full?

The problem is the TextView can potentially contain a different number of lines, depending on whether it is landscape, portrait, small screen, large screen, etc.

Thank you for your advice,

Best regards,

James

James
  • 551
  • 1
  • 5
  • 13

6 Answers6

16

These answers didn't work very well for me. Here's what I ended up doing

Paint measurePaint = new Paint(myTextView.getPaint());
float pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
float labelWidth = myTextView.getWidth();
int maxLines = myTextView.getMaxLines();

while (labelWidth > 0 && pWidth/maxLines > labelWidth-20) {
    float textSize = measurePaint.getTextSize();
    measurePaint.setTextSize(textSize-1);
    pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
    if (textSize < TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP, 7,
            getContext().getResources().getDisplayMetrics())) break;
}

myTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, measurePaint.getTextSize());

I'm not saying this will work for every situation as I'm certainly cutting corners here, but the general idea is to measure the text with the textview's paint and keep shrinking it until it will fit inside the textview.

whizzle
  • 2,053
  • 17
  • 21
10

I have found a "cheeky" solution to the problem of measuring the height of the text in a MULTILINE TextView :-

//Calculate the height of the text in the MULTILINE TextView
int textHeight = textView.getLineCount() * textView.getLineHeight();
if (textHeight > textViewHeight) {
    //Text is truncated because text height is taller than TextView height
} else {
    //Text not truncated because text height not taller than TextView height
}

However this solution has some caveats :-

Firstly regarding getLineHeight() , markup within the text can cause individual lines to be taller or shorter than this height, and the layout may contain additional first- or last-line padding. See http://developer.android.com/reference/android/widget/TextView.html#getLineHeight()

Secondly , the application needs to calculate the actual height of the TextView in pixels , and (in the case of my layout) it might not be as simple as textView.getHeight() , and calculation may vary from one layout to another layout.

I would recommend avoiding LinearLayout because the actual pixel height of the TextView can vary depending on text content. I am using a RelativeLayout (see http://pastebin.com/KPzw5LYd).

Using this RelativeLayout, I can calculate my TextView height as follows :-

//Calculate the height of the TextView for layout "http://pastebin.com/KPzw5LYd"
int textViewHeight = layout1.getHeight() - button1.getHeight() - button2.getHeight();

Hope that helps,

Regards,

James

James
  • 551
  • 1
  • 5
  • 13
4

Basically, you need to calculate the size of your textview and the size of your text when the orientation mode changed. Try ViewTreeObserver.OnGlobalLayoutListener to do so.

Inside the change orientation method:

main_view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            main_view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            //Calculation goes here
            int text_size = getTextSize(text_view.getText().toString());
            int text_view_size = text_view.getLayoutParams().width;
            //Compare your text_size and text_view_size and do whatever you want here.
        }
    });

Here is the code of calculate the text_size:

private int getTextSize(String your_text){
    Paint p = new Paint();
    //Calculate the text size in pixel
    return p.measureText(your_text);
}

Hope this help.

user2652394
  • 1,686
  • 1
  • 13
  • 15
  • 1
    This will not work for me because "p.measureText(your_text)" only calculate text width. It does not calculate text height for a MULTILINE TextView. I have found another solution now, which I will add shortly. – James Aug 07 '13 at 18:57
0

For checking whether a multiline (or not) TextView is going to be truncated, check this post.

Or, have you looked into using a scrolling textview? (marquee).. where the text will scroll by (horizontally, animated) if it is too long for a given width?

Here is an example TextView in a layout file, that has some of these characteristics:

<TextView
    android:id="@+id/sometextview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever"
    android:singleLine="true"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:freezesText="true"
    android:textColor="#808080"
    android:textSize="14sp"
    android:text="This is a long scrolling line of text.. (etc)"/>
Community
  • 1
  • 1
MiStr
  • 1,193
  • 10
  • 17
  • Regarding your XML, this will not work for me because it sets singleLine="true" which is not a MULTILINE TextView. Regarding check this post, this will not work for me because "testPaint.measureText(text)" only calculates text width. It does not calculate text height for a MULTILINE TextView. I have found another solution now, which I will add shortly. – James Aug 07 '13 at 18:58
  • that answer does not deal with multiline text views. It only checks if the text will fill the *width* of the textveiw or not – LairdPleng Nov 08 '15 at 08:40
  • The question is not only asking about multiline; it also asks about "fitting" in a textview... – MiStr Nov 11 '15 at 19:53
0

This extension function in Kotlin worked for me, just make sure to call it when the view is already laied out, e.g. view.post() is a good place for me;

/**
 * Make sure to call this method only when view layout is finished, e.g. view.post() is a good place to check this
 */
fun TextView.isTruncated() = (lineCount * lineHeight) > height

Usage

textView.post {
    if(isTruncated()) {
        // Do something
    }
}
Andranik
  • 2,729
  • 1
  • 29
  • 45
-1

Just check textView.getLineCount(), if line count > 1 then your text is multiline