Ngoài việc vẽ văn bản nhiều dòng, người ta có thể đấu tranh với việc giới hạn văn bản đa dòng (ví dụ để căn chỉnh nó trên khung vẽ).
Mặc định paint.getTextBounds()
sẽ không hoạt động trong trường hợp này vì nó sẽ đo dòng duy nhất.
Để thuận tiện, tôi đã tạo 2 hàm mở rộng này: một để vẽ văn bản nhiều dòng và hai là để lấy giới hạn văn bản.
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
}
Bây giờ sử dụng nó dễ dàng như vậy: Để vẽ văn bản nhiều dòng:
canvas.drawTextMultiLine(text, x, y, yourPaint)
Để đo văn bản:
val bound = yourPaint.getTextBoundMultiLine (văn bản)
Trong trường hợp này, nó sẽ đo tất cả văn bản từ đầu đến cuối và bằng cách sử dụng Rect mặc định được phân bổ (có thể thay đổi).
Bạn có thể chơi xung quanh với việc chuyển các tham số bổ sung để thêm linh hoạt.
Layout
thay vì gọiCanvas.drawText
trực tiếp. Câu hỏi và trả lời này cho thấy cách sử dụng aStaticLayout
để vẽ văn bản nhiều dòng.