En plus de dessiner du texte multiligne, on peut avoir du mal à obtenir les limites du texte multiligne (par exemple pour l'aligner sur le canevas).
Défautpaint.getTextBounds()
ne fonctionnera pas dans ce cas car elle mesurera la seule ligne.
Pour plus de commodité, j'ai créé ces 2 fonctions d'extension: l'une pour dessiner du texte multiligne et l'autre pour obtenir des limites de texte.
private val textBoundsRect = Rect()
/**
* Draws multi-line text on the Canvas with the origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
fun Canvas.drawTextMultiLine(text: String, x: Float, y: Float, paint: Paint) {
var lineY = y
for (line in text.split("\n")) {
lineY += paint.descent().toInt() - paint.ascent().toInt()
drawText(line, x, lineY, paint)
}
}
/**
* Retrieve the text boundary box, taking into account line breaks [\n] and store to [boundsRect].
*
* Return in bounds (allocated by the caller [boundsRect] or default mutable [textBoundsRect]) the smallest rectangle that
* encloses all of the characters, with an implied origin at (0,0).
*
* @param text string to measure and return its bounds
* @param start index of the first char in the string to measure. By default is 0.
* @param end 1 past the last char in the string to measure. By default is test length.
* @param boundsRect rect to save bounds. Note, you may not supply it. By default, it will apply values to the mutable [textBoundsRect] and return it.
* In this case it will be changed by each new this function call.
*/
fun Paint.getTextBoundsMultiLine(
text: String,
start: Int = 0,
end: Int = text.length,
boundsRect: Rect = textBoundsRect
): Rect {
getTextBounds(text, start, end, boundsRect)
val linesCount = text.split("\n").size
val allLinesHeight = (descent().toInt() - ascent().toInt()) * linesCount
boundsRect.bottom = boundsRect.top + allLinesHeight
return boundsRect
}
Maintenant, l'utiliser est aussi simple que cela: Pour dessiner du texte multiligne:
canvas.drawTextMultiLine(text, x, y, yourPaint)
Pour mesurer du texte:
val bounds = yourPaint.getTextBoundsMultiLine (texte)
Dans ce cas, il mesurera tout le texte du début à la fin et avec l'utilisation de la valeur par défaut une fois allouée (mutable) Rect.
Vous pouvez jouer avec le passage de paramètres supplémentaires pour plus de flexibilité.
Layout
au lieu d'appelerCanvas.drawText
directement. Cette Q&R montre comment utiliser aStaticLayout
pour dessiner du texte multiligne.