Search code examples
androidxmlandroid-layouttextview

Android TextView lineCount doesn't return correct value when ellipsize is set


I want to expand and collapse my TextView. So I made these extension functions for doing that.

private const val MAX_LINES_PROPERTY_NAME = "maxLines"
private const val EXPAND_ANIMATION_DURATION = 200L

fun TextView.expand() {
    val animation = ObjectAnimator.ofInt(this, MAX_LINES_PROPERTY_NAME, this.lineCount)
    animation.setDuration(EXPAND_ANIMATION_DURATION).start()
}

fun TextView.collapse(numLines: Int) {
    val animation = ObjectAnimator.ofInt(this, MAX_LINES_PROPERTY_NAME, numLines)
    animation.setDuration(EXPAND_ANIMATION_DURATION).start()
}

Problem appears when I set TextView like this

<TextView
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLines="3"
    android:ellipsize="end"
    android:text="Long text"
    android:textColor="@color/black"
    android:textSize="16sp">

Apparently textView.lineCount returns 3 when ellipsize is set to "end". When I remove that line of code everything works. Does anyone know how can I avoid this?


Solution

  • I found some hacky way to set ellipsize and to get lineCount of whole TextView.

    Firstly, I removed android:ellipsize="end" line in xml.

    After that I saved lineCount locally and I set ellipsize programmatically after doing that.

    private var textLineCount = 0
    
    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        
            textView.post {
                    textLineCount = textView.lineCount
                    textView.ellipsize = TextUtils.TruncateAt.END
            }
    }
    

    Now that I have textLineCount locally, I just pass it in my function for expanding TextView which I modified like this

    fun TextView.expand(maxLines: Int? = null) {
        val animation = ObjectAnimator.ofInt(this, MAX_LINES_PROPERTY_NAME, maxLines ?: this.lineCount)
        animation.setDuration(EXPAND_ANIMATION_DURATION).start()
    }
    

    And that's it. I know it's not the happiest solution, but it works. If anyone knows better, please share your solution.