Ellipsize not working properly for a multiline TextView with an arbitrary maximum height
Calculate how many lines fit into the TextView
with TextView#getHeight()
and TextView#getLineHeight()
. Then call TextView#setMaxLines()
.
ViewTreeObserver observer = textView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int maxLines = (int) textView.getHeight()
/ textView.getLineHeight();
textView.setMaxLines(maxLines);
textView.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
The accepted answer works well up to API 27. However, since API 28, if the line height was not set (by one of the follow methods), by default Android adds extra spacing between lines, but not after the last line.
- Set attribute
android:lineHeight=...
(documentation) in your layout XML - Calls
textView.setLineHeight(...)
in your source code.
To find out the new line height for API 28 and above, I used textView.getLineBounds()
.
Kotlin
val observer = textView?.viewTreeObserver
observer?.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
textView?.let { view ->
val lineHeight: Int
lineHeight = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val bounds = Rect()
textView.getLineBounds(0, bounds)
bounds.bottom - bounds.top
} else {
textView.lineHeight
}
val maxLines = textView.height / lineHeight
textView.maxLines = maxLines
textView.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
})
Android Java
ViewTreeObserver observer = textView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int lineHeight = textView.getLineHeight();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Rect bounds = new Rect();
textView.getLineBounds(0, bounds);
lineHeight = bounds.bottom - bounds.top;
}
int maxLines = (int) textView.getHeight() / lineHeight;
textView.setMaxLines(maxLines);
textView.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});