Определите, где Android TextView вставит разрыв строки

У меня есть прямоугольная плитка, и я хочу поместить в нее изображение и текст. Изображение не должно накладываться на текст, а размеры изображения и текста могут различаться.

Процесс должен быть закодирован вручную, так как мы должны настроить его в соответствии с потребностями нашего клиента.

Я попробовал сначала измерить границы отображаемого текста с помощью getTextBounds() или measureText(), а затем адаптировать размер шрифта и размер изображения, чтобы они не перекрывались.

Это прекрасно работает, если текст находится только на одной строке.

Но если TextView переносит текст на несколько строк, я не могу предсказать границы текста, так как я не знаю, где TextView будет вставлять автоматические разрывы строк.

Как узнать позиции в тексте, где TextView вставляет автоматический разрыв строки?

Пример: данный текст

Lorem ipsum dolor sit amet

который будет отображаться как

| Lorem ipsum    |
| dolor sit amet |

Мне нужна функция, которая преобразует

Lorem ipsum dolor sit amet

to

Lorem ipsum \ndolor sit amet


person cheesus    schedule 14.10.2014    source источник
comment
см. класс StaticLayout   -  person pskink    schedule 14.10.2014


Ответы (2)


TextView (объект макета) имеет несколько полезных функций для того, что вы пытаетесь выполнить:

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

Взгляни на:

getLineCount()

getLineEnd(int line)

Вы можете получить подстроку для строки TextView в зависимости от того, где находится символ в конце каждой строки.

Вам нужно будет использовать getViewTreeObserver(), чтобы дождаться отрисовки TextView, прежде чем вы сможете вызвать их и получить от них полезную информацию.

В качестве альтернативы вы можете создать собственный TextView, который может предоставлять данные с помощью встроенных методов или путем добавления к нему прослушивателя. Пример пользовательского TextView, который изменяет размер текста, находится здесь:

многострочное текстовое представление для Android с размером эллипса

Я использовал это и делал аналогичные модификации (например, то, что вы пытаетесь сделать).

person Jim    schedule 14.10.2014
comment
Если TextView уже нарисован, вы должны вызвать его из другого потока, иначе количество строк будет неправильным. textview.post(new Runnable{ int lineCount = textview.getLineCount(); }); - person Juan José Melero Gómez; 11.01.2017

Вы, вероятно, захотите поместить эту логику в собственное представление (переопределяя onSizeChanged()), но вы можете использовать класс Layout, чтобы проверить, где заканчивается каждая строка:

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));
        }
    }
});
person Kevin Coppock    schedule 14.10.2014