Background
I know how to set multiple spans on a partial text within a static text, as I've asked here :
final SpannableString text = new SpannableString("Hello stackOverflow");
text.setSpan(new RelativeSizeSpan(1.5f), text.length() - "stackOverflow".length(), text.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new ForegroundColorSpan(Color.RED), 3, text.length() - 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(text);
This will set the "stackOverflow" to have 2 spans on itself.
I also know how to set a drawable span on a part of the text, as I've asked here.
The problem
Now I need to set 2 spans on a text that's generated from formatting a text with a placeholder, while still having other styles being set as usual.
For example, suppose I have the next text in strings.xml:
<string name="potential_free_upgrade_1_d_months">
<![CDATA[
Potential free upgrade: <uu><b><font color=\'#3792e5\'>%1$d months</font></b></uu>]]>
</string>
The plan is that "%1$d months" will have a text color of "#3792e5" and will have a special underline that is a bit more below than the default one. I used a special customized tag "uu" for the special underline, to be handled in code.
Thing is, no matter what I do, I can't find how to have both the text color AND the underline being shown together.
What I've tried
Since this problem has a placeholder (and the text can be different around the text to be formatted), I had to use "Html.FromHtml" :
String formattedStr = getString(R.string.potential_free_upgrade_1_d_months, 9);
Spanned textToShow = Html.fromHtml(formattedStr, null, new TagHandler() {
int start;
@Override
public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) {
switch (tag) {
case "uu":
if (opening)
start = output.length();
else {
int end = output.length();
//output.setSpan(new ForegroundColorSpan(0xff3792e5), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
output.setSpan(
new DrawableSpan(ResourcesCompat.getDrawable(getResources(), R.drawable.bit_below_underline, null)),
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
});
titleTextView.setText(textToShow);
DrawableSpan.java
public class DrawableSpan extends ReplacementSpan {
private Drawable mDrawable;
private final Rect mPadding;
public DrawableSpan(Drawable drawable) {
super();
mDrawable = drawable;
mPadding = new Rect();
mDrawable.getPadding(mPadding);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
RectF rect = new RectF(x, top, x + measureText(paint, text, start, end), bottom);
mDrawable.setBounds((int) rect.left - mPadding.left, (int) rect.top - mPadding.top, (int) rect.right + mPadding.right, (int) rect.bottom + mPadding.bottom);
canvas.drawText(text, start, end, x, y, paint);
mDrawable.draw(canvas);
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
return Math.round(paint.measureText(text, start, end));
}
private float measureText(Paint paint, CharSequence text, int start, int end) {
return paint.measureText(text, start, end);
}
}
res/drawable/bit_below_underline.xml
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<padding android:bottom="30dp"/>
<stroke
android:width="1dp"
android:color="#3792e5"/>
</shape>
I tried to call the 2 "setSpan" together (first is commented in the code above), but it didn't help.
The question
How can I set 2 spans on the part of the text, as I've specified above (partial text with placeholder) , so that one will be of text-color, and another of an customized-underline ?