Обтекание длинного текста на холсте Android

У меня есть пользовательский элемент управления, который выполняет много 2D-рисования прямо в canvas.

Часть этого рисунка является текстом, поэтому я использую Canvas.drawText().

Я хочу нарисовать текст в некоторых пределах - в левом верхнем углу, с определенной максимальной шириной и максимальным количеством строк. После рисования текста я хочу знать, сколько строк он занял.

Есть ли встроенная функция для рисования текста в границах, разумно выполняющая разделение?

Если нет, то есть ли стандартный рецепт для этого?


person Will    schedule 25.02.2010    source источник
comment
См. этот ответ для хорошего примера использования StaticLayouts: stackoverflow.com/a/8369690/293280   -  person Joshua Pinter    schedule 26.05.2015


Ответы (3)


Для этого вы можете использовать класс android.text.StaticLayout; просто создайте StaticLayout для нужного текста, выравнивания, ширины и т. д. и вызовите его метод draw(Canvas) для рисования на холсте.

person Roman Nurik    schedule 25.02.2010
comment
Удивительно, что я проглядел это - person Will; 26.02.2010
comment
Это только для андроида? А как насчет других платформ? - person B Seven; 07.05.2011
comment
Здорово! Как бы вы центрировали текст на холсте? - person Tim Kist; 22.05.2013
comment
@zboarda Не уверен, что вы имеете в виду, но пробовали ли вы Paint.setTextAlign(Align.CENTER); ? - person Ray Britton; 07.07.2013
comment
@Eenvincible см. мой пост в блоге skoumal.net/en/android -рисование-многострочного-текста-на-растровом - person gingo; 15.11.2015

Вы можете использовать Paint.getTextBounds() для измерения размера всей строки или Paint.getTextWidths() для получения ширины каждого символа. Затем разделите строку соответствующим образом, прежде чем рисовать ее.

person Alexander    schedule 25.07.2012

У меня такая же проблема. Одно из моих первых решений следующее.

/**
     * This function draws the text on the canvas based on the x-, y-position.
     * If it has to break it into lines it will do it based on the max width
     * provided.
     * 
     * @author Alessandro Giusa
     * @version 0.1, 14.08.2015
     * @param canvas
     *            canvas to draw on
     * @param paint
     *            paint object
     * @param x
     *            x position to draw on canvas
     * @param y
     *            start y-position to draw the text.
     * @param maxWidth
     *            maximal width for break line calculation
     * @param text
     *            text to draw
     */
public static void drawTextAndBreakLine(final Canvas canvas, final Paint paint,
        final float x, final float y, final float maxWidth, final String text) {
    String textToDisplay = text;
    String tempText = "";
    char[] chars;
    float textHeight = paint.descent() - paint.ascent();
    float lastY = y;
    int nextPos = 0;
    int lengthBeforeBreak = textToDisplay.length();
    do {
        lengthBeforeBreak = textToDisplay.length();
        chars = textToDisplay.toCharArray();
        nextPos = paint.breakText(chars, 0, chars.length, maxWidth, null);
        tempText = textToDisplay.substring(0, nextPos);
        textToDisplay = textToDisplay.substring(nextPos, textToDisplay.length());
        canvas.drawText(tempText, x, lastY, paint);
        lastY += textHeight;
    } while(nextPos < lengthBeforeBreak);
}

Чего не хватает:

  • Нет интеллектуального механизма разрыва строки, так как он разрывается на основе maxWidth

Как позвонить?

    paint.setTextSize(40);
    paint.setColor(Color.WHITE);
    paint.setSubpixelText(true);
    float textHeight = paint.descent() - paint.ascent();
    CanvasUtils.drawTextAndBreakLine(canvas, paint, this.left,
            textHeight, this.displayWidth, this.text);

У меня есть статический класс CanvasUtils, в котором я инкапсулирую подобные вещи. В основном я рисую текст внутри прямоугольника. По этой причине textHeight является высотой текста. Но вы можете передать в функцию то, что хотите.

Хорошее программирование!

person Alessandro Giusa    schedule 14.08.2015
comment
Да, это сработало для меня, но это заставляет слова ломаться! Есть ли способ исправить это? - person Eenvincible; 07.11.2015
comment
Эй, Eenvincible, ты имеешь в виду отдельные слова? Перенос? - person Alessandro Giusa; 07.11.2015
comment
Не в частности. что происходит с этим кодом, так это то, что текст правильно обтекается внутри прямоугольника, но некоторые слова обрезаются, в конечном итоге разбиваясь на новые строки, при этом часть слов отображается в одной строке, а часть - в следующей строке. - person Eenvincible; 07.11.2015
comment
Это то, что я говорил. И вы хотели бы иметь алгоритм, который правильно расставляет переносы, или алгоритм, который просто помещает затронутое слово в следующую строку? - person Alessandro Giusa; 08.11.2015