46

I am trying to construct a SpannableString such that it looks like this:

enter image description here

Two characters (m, s) should be smaller than the rest. I have tried to hold all the text in one SpannableString, and I also tried to concatenate two SpannableStrings via a SpannableStringBuilder. The code for one Spannable looks like this:

spannable.setSpan(new RelativeSizeSpan(0.75f), spannable.length() - 1, spannable.length(), 0);

However, only one formatting is applied - when using the SpannableStringBuilder, only the "m" is smaller, and when using one SpannableString for the whole text, only the "s" is smaller.

Debugging also showed that Spannables seem to hold only one instance of RelativeSizeSpan, meaning there can be only one Span of one type. Is this true or expected behaviour? Would it be advisable to concatenate TextViews instead?

EDIT: By the way, I am trying to remove a HTML.fromHtml() call here for performance reasons (many GC calls).

manmal
  • 3,581
  • 1
  • 27
  • 39

4 Answers4

117

If you're still looking for an answer, I might have a solution. I had similar problems. I used TextUtils to concat the 2 SpannableString.

Here is some example code:

SpannableString span1 = new SpannableString("32m");
SpannableString span2 = new SpannableString("50s");

span1.setSpan(new RelativeSizeSpan(0.75f),  2, 3, 0);
span2.setSpan(new RelativeSizeSpan(0.75f),  2, 3, 0);

mTextView.setText(TextUtils.concat(span1," " ,span2));
ישו אוהב אותך
  • 22,515
  • 9
  • 59
  • 80
Norman
  • 2,331
  • 1
  • 18
  • 16
  • 2
    Also note that `ClickableSpan` won't work without `textView.movementMethod = LinkMovementMethod.getInstance()` – Bugs Happen Dec 24 '19 at 13:03
14

You don't need 2 separate SpannableString. A shorter solution can be :

SpannableString span1 = new SpannableString("32m50s");

span1.setSpan(new RelativeSizeSpan(0.75f),  2, 3, 0);
span1.setSpan(new RelativeSizeSpan(0.75f),  5, 6, 0);

mTextView.setText(span1);
gbero
  • 3,820
  • 1
  • 22
  • 30
3

You can use array of SpannableString.

Like in this case:

TextView lblDescription=(TextView ) findViewById(R.id.lblDescription);

SpannableString[] finalString = new SpannableString[stringSplit.length];

lblDescription.setText(TextUtils.concat(finalString));
Eric Aya
  • 68,765
  • 33
  • 165
  • 232
AlexPad
  • 7,531
  • 2
  • 27
  • 39
1

I have using dynamic version of gbero's answer in my project,

public void updateTime(TextView tv) {

    Calendar calendar = Calendar.getInstance();

    SpannableString span = new SpannableString(
            calendar.get(Calendar.HOUR_OF_DAY) + "h" + calendar.get(Calendar.MINUTE) + "m");

    span.setSpan(new RelativeSizeSpan(0.75f), 2, 3, 0);
    span.setSpan(new RelativeSizeSpan(0.75f), 5, 6, 0);

    tv.setText(span);
}
Hitesh Sahu
  • 31,496
  • 11
  • 150
  • 116
  • this would be wrong sometimes. Your hour might give leading 0 or minute can be double or single digit. And at that case your start/end point for setSpan() would be different. – Alex Jul 11 '16 at 22:18