I\'m trying to format Hashtags inside a TextView/EditText (Say like Chips mentioned in the Material Design Specs). I\'m able to format the background using ReplacementSpan
Text markup in Android is so poorly documented, writing this code is like feeling your way through the dark.
I've done a little bit of it, so I will share what I know.
You can handle line spacing by wrapping your chip spans inside a The This method is called for each line in your paragraph So what the Here's an example I did for a bullet item in a list (think Your version will probably be even simpler, just changing the When it comes to deciphering the LineHeightSpan
. LineHeightSpan
is an interface that extends the ParagraphStyle
marker interface, so this tells you it affects appearance at a paragraph level. Maybe a good way to explain it is to compare your ReplacementSpan
subclass to an HTML , whereas a
ParagraphStyle
span like LineHeightSpan
is like an HTML LineHeightSpan
interface consists of one method:public void chooseHeight(CharSequence text, int start, int end,
int spanstartv, int v,
Paint.FontMetricsInt fm);
text
is your Spanned
string.start
is the index of the character at the start of the current lineend
is the index of the character at the end of the current linespanstartv
is (IIRC) the vertical offset of the entire span itselfv
is (IIRC) the vertical offset of the current linefm
is the FontMetrics
object, which is actually a returned (in/out) parameter. Your code will make changes to fm
and TextView
will use those when drawing.TextView
will do is call this method once for every line it processes. Based on the parameters, along with your Spanned
string, you set up the FontMetrics
to render the line with the values of your choosing.
) where I wanted some separation between each list item: @Override
public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, Paint.FontMetricsInt fm) {
int incr = Math.round(.36F * fm.ascent); // note: ascent is negative
// first line: add space to the top
if (((Spanned) text).getSpanStart(this) == start) {
fm.ascent += incr;
fm.top = fm.ascent + 1;
}
// last line: add space to the bottom
if (((Spanned) text).getSpanEnd(this) == end) {
fm.bottom -= incr;
}
}
FontMetrics
the same way for each line that it's called.FontMetrics
, the logger and debugger are your friends. You'll just have to keep tweaking values until you get something you like.