I have implemented that using the concept of this answer.
You can create an extension function like this-
/**
* Calculate max lines according height
*
* @param text- text need to be set
* @param lineCount- invoked with -1 if view height is enough to show full text,
* otherwise invoked with maxLines
*/
inline fun TextView.calculateMaxLines(text: String, crossinline lineCount: (Int) -> (Unit)) {
val params: PrecomputedTextCompat.Params = TextViewCompat.getTextMetricsParams(this)
val ref: WeakReference<TextView>? = WeakReference(this)
GlobalScope.launch(Dispatchers.Default) {
val computedText = PrecomputedTextCompat.create(text, params)
ref?.get()?.apply {
TextViewCompat.setPrecomputedText(this, computedText)
GlobalScope.launch(Dispatchers.Main) {
ref.get()?.let {
val bounds = it.getLineBounds(0, null)
val heightRequired = bounds * it.lineCount
val maxLines = if (heightRequired > height) {
height / bounds
} else -1
lineCount.invoke(maxLines)
}
}
}
}
}
Then you can call it and set maxLines like this-
textView.calculateMaxLines("Line 1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8") {
if (it >= 0) {
tvUserName.maxLines = it
tvUserName.ellipsize = TextUtils.TruncateAt.END
}
}
Or, for Java you can call it like this-
ExtensionsKt.calculateMaxLines(textView, text, maxLines -> {
if (maxLines >= 0) {
textView.setMaxLines(maxLines);
textView.setEllipsize(TextUtils.TruncateAt.END);
}
return null;
});