yongsunCN
yongsunCN

Reputation: 766

Android TextVIew Ellipsis based on view size

I'm trying to set ellipsis to the end of my text(multi-line) if the text is too long.

I already know I can use setMaxLines() and setEllipsize() to achieve the effect. However, since my textview's size is dynamically changeable, I don't know the max number of lines that can be displayed. Instead I have the textview's height (by pixel).

How do I set ellipsis based on the height of the view and the text(includes font properties)? If no direct available resource I can use, what could be the easiest possible approach?

Upvotes: 3

Views: 1598

Answers (2)

Barno
Barno

Reputation: 786

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;
        });

Upvotes: 0

Buddy
Buddy

Reputation: 11028

You can use getLineCount() (but only after a layout pass).

See this answer for more information.

Upvotes: 2

Related Questions