Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect where Android's TextView would insert a line break

I have a rectangular tile, and I want to fit an image and some text into it. The image must not overlap the text, and the sizes of the image and the text can vary.

The process must be hand-coded, since we have to fine-tune it according to our client's needs.

I tried the approach of first measuring the rendered text bounds using getTextBounds() or measureText() and then adapting the font size and the image size so they don't overlap.

This works fine if the text is only on one line.

But if TextView wraps the text onto multiple line, I cannot predict the text bounds, since I don't know where TextView would insert the automatic line breaks.

How can I find out the positions in the text where TextView inserts an automatic line break?

Example: Given the text

Lorem ipsum dolor sit amet

which would be rendered as

| Lorem ipsum    |
| dolor sit amet |

I need a function that converts

Lorem ipsum dolor sit amet

to

Lorem ipsum \ndolor sit amet

like image 778
cheesus Avatar asked Oct 14 '14 16:10

cheesus


2 Answers

TextView (Layout object) has some useful functions for what you are trying to accomplish:

http://developer.android.com/reference/android/text/Layout.html

take a look at:

getLineCount()

getLineEnd(int line)

You can get the substring for the TextView string based on where the character is located at each lineEnd.

You will need to use getViewTreeObserver() to wait until the TextView is drawn before you can call these and get useful information from them.

Alternatively, you can build a custom TextView that might provide the data through built-in methods or by adding a listener to it. An example of a custom TextView that modifies text size is here:

android ellipsize multiline textview

I've used that and did similar modifications (like what you are trying to do).

like image 188
Jim Avatar answered Oct 06 '22 01:10

Jim


You'd probably want to wrap this logic into a custom view (overriding onSizeChanged()) but you can use the Layout class to check where each line ends:

textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Remove immediately so it only fires once
        textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        // View should be laid out, including text placement
        final Layout layout = textView.getLayout();
        float maxLineWidth = 0;

        // Loop over all the lines and do whatever you need with
        // the width of the line
        for (int i = 0; i < layout.getLineCount(); i++) {
            maxLineWidth = Math.max(maxLineWidth, layout.getLineWidth(i));
        }
    }
});
like image 23
Kevin Coppock Avatar answered Oct 06 '22 01:10

Kevin Coppock