I want to draw a SpannedString to a Canvas.
SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(foregroundSpan, 1, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(backgroundSpan, 3, spannableString.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
The above example was drawn using a TextView, which in turn uses a Layout to draw text with spans. I know that using a Layout is the recommended way to draw text to the canvas. However, I am making my own text layout from scratch, so I need to implement this myself.
Doing something like this doesn't work
canvas.drawText(spannableString, 0, spannableString.length(), 0, 0, mTextPaint);
because drawText only gets the text from the spannableString, not any of the spans. The drawing colors are handled separately by TextPaint.
How do I use canvas.drawText (or drawTextRun) to draw the span information (specifically foreground and background color here)?
Related
- How to loop through the spans in a SpannedString or SpannableString in Android
- Is it possible to display multi-color text with one call to Canvas.drawText()?
Plan for a solution
I was going to directly do a self answer but this is turning out to be more difficult than I thought. So I will post first and then add an answer whenever I can figure it out. (I would of course welcome anyone to answer first.)
Here are the pieces that I have so far:
- Draw each span range as a separate text run
- Use
drawTextRunto draw the text (examples) (update: not added until API 23) - Use
getRunAdvanceto measure where to start the next text run (update: not added until API 23, usemeasureTextinstead) - The background color will probably need to be drawn separately (with
drawRector maybedrawPath? See here, here, and here.) - Source code for
TextView,StaticLayout, andTextLine

