Search code examples
androidkotlintextview

How to detect line breaks in TextView


In my Android App I've created 8 TextViews stacked on top of each other. Now I want to load in some plain text into those TextView-Lines. At the moment my Strings have a ";" as delimiter to indicate a line break, however it would be much more convenient if I would detect a linebreak automatically instead of using the hardcoded semicolon approach.

This is my String at the moment:

myString = "" +
"This seems to be some sort of spaceship,;" +
"the designs on the walls appear to be of;" +
"earth origin. It looks very clean here.;"

And in my other class I load in this string into the 8 TextViews, which I've loaded into an ArrayList, using the ";" as a delimiter.

public fun fillLines(myString: String) {
    // How To Make Line Breaks Automatic??

    for(i: Int in str until myString.split(";").size) {
        if(i > textViewArray.size - 1) {
            break
        }
        textViewArray[i].text = myString.split(";")[i]
        textViewArray[i].alpha = 1.0f
    }
}

Is there any way I can get the same result as shown above but without hardcoding the delimiter as ";" but instead somehow automatically detect the line break which would occur inside the TextView and then use this as a delimiter to advance through all 8 TextView "Lines".

The reason I need 8 TextViews Stacked On top of each other as individual "text lines" is because of an animation technique I want to use.


Solution

  • Line-breaking gets fairly complicated, so my recommendation would be that you allow a TextView to perform the measuring and layout to determine the line breaks. You could have an invisible TextView with the same style as your other views, and attach it to the layout so that it has the same width as your individual TextView instances. From there, add a layout change listener, and you can then retrieve the individual lines from the TextView Layout:

    myTextView.text = // your text string here
    myTextView.addOnLayoutChangeListener { view, _, _, _, _, _, _, _, _ ->
        (view as? TextView)?.layout?.let { layout ->
            // Here you'll have the individual broken lines:
            val lines = (0 until layout.lineCount).map {
                layout.text.subSequence(layout.getLineStart(it), layout.getLineVisibleEnd(it)
            }
        }
    }
    

    That said, this comes with the caveat that you'll lose out on hyphenation provided by the TextView, so you may wish to disable hyphenation entirely in your case.