How do I tell if my textview has been ellipsized?

AndroidTextviewEllipsis

Android Problem Overview


I have a multi-line TextView that has android:ellipsize="end" set. I would like to know, however, if the string I place in there is actually too long (so that I may make sure the full string is shown elsewhere on the page).

I could use TextView.length() and find about what the approximate length of string will fit, but since it's multiple lines, the TextView handles when to wrap, so this won't always work.

Any ideas?

Android Solutions


Solution 1 - Android

You can get the layout of the TextView and check the ellipsis count per line. For an end ellipsis, it is sufficient to check the last line, like this:

Layout l = textview.getLayout();
if (l != null) {
	int lines = l.getLineCount();
	if (lines > 0)
		if (l.getEllipsisCount(lines-1) > 0)
			Log.d(TAG, "Text is ellipsized");
}

This only works after the layout phase, otherwise the returned layout will be null, so call this at an appropriate place in your code.

Solution 2 - Android

textView.getLayout is the way to go but the problem with that is that it returns null if layout is not prepared. Use the below solution.

 ViewTreeObserver vto = textview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
           Layout l = textview.getLayout();
           if ( l != null){
              int lines = l.getLineCount();
              if ( lines > 0)
                  if ( l.getEllipsisCount(lines-1) > 0)
                    Log.d(TAG, "Text is ellipsized");
           }  
        }
    });

Code snippet for removing the listener (source):

mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);        
    }
});

Solution 3 - Android

I think the easiest solution to this question is the following code:

String text = "some looooong text";
textView.setText(text);
boolean isEllipsize = !((textView.getLayout().getText().toString()).equalsIgnoreCase(text));

This code assumes that in your XML the TextView set a maxLineCount :)

Solution 4 - Android

This worked to me:

textView.post(new Runnable() {
                        @Override
                        public void run() {
                            if (textView.getLineCount() > 1) {
                                //do something
                            }
                        }
                    });

Solution 5 - Android

The most eloquent solution I have found (in Kotlin) is to create an extension function on TextView

fun TextView.isEllipsized() = layout.text.toString() != text.toString()

This is great because it doesn't require knowing what the full string is or worrying about how many lines the TextView is using.

TextView.text is the full text that it's trying to show, whereas TextView.layout.text is what's actually shown on the screen so if they are different it must be getting ellipsized

To use it:

if (my_text_view.isEllipsized()) {
    ...
}

Solution 6 - Android

public int getEllipsisCount (int line):

>Returns the number of characters to be ellipsized away, or 0 if no ellipsis is to take place.

So, simply call :

int lineCount = textview1.getLineCount();

if(textview1.getLayout().getEllipsisCount(lineCount) > 0) {
   // Do anything here..
}

Since the getLayout() cant be called before the layout is set, use this:

ViewTreeObserver vto = textview.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
       Layout l = textview.getLayout();
       if ( l != null){
          int lines = l.getLineCount();
          if ( lines > 0)
              if ( l.getEllipsisCount(lines-1) > 0)
                Log.d(TAG, "Text is ellipsized");
       }  
    }
});

And finally do not forget to remove removeOnGlobalLayoutListener when you need it nomore.

Solution 7 - Android

lateinit var toggleMoreButton: Runnable
toggleMoreButton = Runnable {
  if(reviewTextView.layout == null) { // wait while layout become available
       reviewTextView.post(toggleMoreButton) 
       return@Runnable
  }
  readMoreButton.visibility = if(reviewTextView.layout.text.toString() != comment) View.VISIBLE else View.GONE
}
reviewTextView.post(toggleMoreButton)

It is some typical case:

  1. comment in 'reviewTextView'
  2. comment can collapsed by some criteria
  3. if comment collapsed you show button 'readMoreButton'

Solution 8 - Android

The Kotlin way:

textView.post {
   if (textView.lineCount > MAX_LINES_COLLAPSED) {
   // text is not fully displayed
   }
}

Actually View.post() is executed after the view has been rendered and will run the function provided

Solution 9 - Android

Simple Kotlin method. Allows android:ellipsize and android:maxLines to be used

fun isEllipsized(textView: TextView, text: String?) = textView.layout.text.toString() != text

Solution 10 - Android

it is working for me

if (l != null) {
    int lines = l.getLineCount();
     if (lines > 0) {
     for (int i = 0; i < lines; i++) {
     if (l.getEllipsisCount(i) > 0) {
      ellipsize = true;
      break;
     }
    }
   }
  }

Solution 11 - Android

Solution with kotlin extensions:

infoText.afterLayoutConfiguration {
    val hasEllipsize = infoText.hasEllipsize()
    ...
}

Extensions:

/**
 * Function for detect when layout completely configure.
 */
fun View.afterLayoutConfiguration(func: () -> Unit) {
    viewTreeObserver?.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            viewTreeObserver?.removeOnGlobalLayoutListener(this)
            func()
        }
    })
}

fun TextView.hasEllipsize(): Boolean = layout.getEllipsisCount(lineCount - 1) > 0

Solution 12 - Android

Really work so, for example, to pass full data to dialog from item of RecyclerView:

holder.subInfo.post(new Runnable() {
                @Override
                public void run() {
                    Layout l = holder.subInfo.getLayout();
                    if (l != null) {
                        final int count = l.getLineCount();
                        if (count >= 3) {
                            holder.subInfo.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    final int c = holder.subInfo.getLineCount();
                                    if (c >= 3) {
                                        onClickToShowInfoDialog.showDialog(holder.title.getText().toString(), holder.subInfo.getText().toString());
                                    }
                                }
                            });
                        }
                    }
                }
            });

Solution 13 - Android

Combining @Thorstenvv awnser with @Tiano fix, here is the Kotlin version :

val layout = textView.layout ?: return@doOnLayout
val lines = layout.lineCount
val hasLine = lines > 0
val hasEllipsis = ((lines - 1) downTo 0).any { layout.getEllipsisCount(it) > 0 }
if (hasLine && hasEllipsis) {
	// Text is ellipsized
}

Solution 14 - Android

In Kotlin, you can use the below code.

var str= "Kotlin is one of the best languages."
textView.text=str
textView.post {
val isEllipsize: Boolean = !textView.layout.text.toString().equals(str)

if (isEllipsize) {
     holder.itemView.tv_viewMore.visibility = View.VISIBLE
} else {
     holder.itemView.tv_viewMore.visibility = View.GONE
}    
}

Solution 15 - Android

This is simple library for creating textview expandable. Like Continue or Less. This library extended version TextView. Easy to use.

implementation 'com.github.mahimrocky:ShowMoreText:1.0.2'

Like this, 1 https://raw.githubusercontent.com/mahimrocky/ShowMoreText/master/screenshot1.png

2 https://raw.githubusercontent.com/mahimrocky/ShowMoreText/master/screenshot2.png

 <com.skyhope.showmoretextview.ShowMoreTextView
    android:id="@+id/text_view_show_more"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/text"
    />

In Activity you can use like:

ShowMoreTextView textView = findViewById(R.id.text_view_show_more);

//You have to use following one of method    

// For using character length
textView.setShowingChar(numberOfCharacter);
//number of line you want to short
textView.setShowingLine(numberOfLine);

Solution 16 - Android

If your textview contains multiple paragraphs, using getEllipsisCount will not work for empty lines within it. getEllipsisCount for the last line of any paragraph will return 0.

Solution 17 - Android

Using getEllipsisCount won't work with text that has empty lines within it. I used the following code to make it work :

message.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {

            if(m.isEllipsized == -1) {
                Layout l = message.getLayout();
                if (message.getLineCount() > 5) {
                    m.isEllipsized = 1;
                    message.setMaxLines(5);
                    return false;
                } else {
                    m.isEllipsized = 0;
                }
            }
            return true;
        }
    });

Make sure not to set a maxLineCount in your XML. Then you can check for the lineCount in your code and if it is greater than a certain number, you can return false to cancel the drawing of the TextView and set the line count as well as a flag to save whether the text view is too long or not. The text view will draw again with the correct line count and you will know whether its ellipsized or not with the flag.

You can then use the isEllipsized flag to do whatever you require.

Solution 18 - Android

create a method inside your TextViewUtils class

public static boolean isEllipsized(String newValue, String oldValue) {
    return !((newValue).equals(oldValue));
}

call this method when it's required eg:

        if (TextViewUtils.isEllipsized(textviewDescription.getLayout().getText().toString(), yourModelObject.getDescription()))
            holder.viewMore.setVisibility(View.VISIBLE);//show view more option
        else
            holder.viewMore.setVisibility(View.GONE);//hide 

but textView.getLayout() can't call before the view(layout) set.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFrederickCookView Question on Stackoverflow
Solution 1 - AndroidThorstenvvView Answer on Stackoverflow
Solution 2 - AndroidHimanshu VirmaniView Answer on Stackoverflow
Solution 3 - AndroidFrancesco FlorioView Answer on Stackoverflow
Solution 4 - AndroidCícero MouraView Answer on Stackoverflow
Solution 5 - AndroidMatt SmithView Answer on Stackoverflow
Solution 6 - AndroidamalBitView Answer on Stackoverflow
Solution 7 - AndroidA.Y.View Answer on Stackoverflow
Solution 8 - Android4ndro1dView Answer on Stackoverflow
Solution 9 - AndroidChaseosView Answer on Stackoverflow
Solution 10 - AndroidcoffeeView Answer on Stackoverflow
Solution 11 - AndroidSerjantArbuzView Answer on Stackoverflow
Solution 12 - Androidnicolas asinovichView Answer on Stackoverflow
Solution 13 - AndroidVictorView Answer on Stackoverflow
Solution 14 - AndroidhetsgandhiView Answer on Stackoverflow
Solution 15 - AndroidGershon TussonView Answer on Stackoverflow
Solution 16 - AndroidDuke CaesarView Answer on Stackoverflow
Solution 17 - Androidjs123View Answer on Stackoverflow
Solution 18 - AndroidAbdul RizwanView Answer on Stackoverflow