The code below draws multiline text on a canvas.
fun Canvas.drawMultilineText(
text: CharSequence,
textPaint: TextPaint,
width: Int,
x: Float,
y: Float,
start: Int = 0,
end: Int = text.length,
alignment: Layout.Alignment = Layout.Alignment.ALIGN_NORMAL,
spacingMult: Float = 1f,
spacingAdd: Float = 0f,
includePad: Boolean = true,
ellipsizedWidth: Int = width,
ellipsize: TextUtils.TruncateAt? = null) {
val cacheKey = "$text-$start-$end-$textPaint-$width-$alignment-" +
"$spacingMult-$spacingAdd-$includePad-$ellipsizedWidth-$ellipsize"
val staticLayout = StaticLayoutCache[cacheKey] ?: StaticLayout.Builder.obtain(text, start, end, textPaint, width)
.setAlignment(alignment)
.setLineSpacing(spacingAdd, spacingMult)
.setIncludePad(includePad)
.setEllipsizedWidth(ellipsizedWidth)
.setEllipsize(ellipsize)
.build()
staticLayout.draw(this, x, y)
}
private fun StaticLayout.draw(canvas: Canvas, x: Float, y: Float) {
canvas.withTranslation(x, y) {
draw(this)
}
}
private object StaticLayoutCache {
private const val MAX_SIZE = 50 // Arbitrary max number of cached items
private val cache = lruCache<String, StaticLayout>(MAX_SIZE)
operator fun set(key: String, staticLayout: StaticLayout) {
cache.put(key, staticLayout)
}
operator fun get(key: String): StaticLayout? {
return cache[key]
}
}
This is how I draw a piece of text:
val textPaint = TextPaint()
textPaint.textSize = 10f
canvas.drawMultilineText(myString, textPaint, canvas.width, 100f, 100f)
It works well. But, I did not find a way to add another piece of text underneath that with a different textPaint. Only solution I found is adding a new text with a different y position as below, but that's not elegant because there's overlapping if myString
is too long. So, what should I do?
val textPaint2 = TextPaint()
textPaint2.textSize = 5f
canvas.drawMultilineText("This is text underneath myString", textPaint2, canvas.width, 100f, 200f)
from Add extra line on canvas with different textual properties
No comments:
Post a Comment