178

I have a textView inside with a number (variable) and a string, how can I give the number one size larger than the string? the code:

TextView size = (TextView)convertView.findViewById(R.id.privarea_list_size);
if (ls.numProducts != null) {
    size.setText(ls.numProducts + " " + mContext.getString(R.string.products));
}

I want ls.numproducts has a size different from the rest of the text. How to do?

AskNilesh
  • 67,701
  • 16
  • 123
  • 163
Ortensia C.
  • 4,666
  • 11
  • 43
  • 70

13 Answers13

419

Use a Spannable String

 String s= "Hello Everyone";
 SpannableString ss1=  new SpannableString(s);
 ss1.setSpan(new RelativeSizeSpan(2f), 0,5, 0); // set size
 ss1.setSpan(new ForegroundColorSpan(Color.RED), 0, 5, 0);// set color
 TextView tv= (TextView) findViewById(R.id.textview);
 tv.setText(ss1); 

Snap shot

enter image description here

You can split string using space and add span to the string you require.

 String s= "Hello Everyone";  
 String[] each = s.split(" ");

Now apply span to the string and add the same to textview.

AskNilesh
  • 67,701
  • 16
  • 123
  • 163
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
151

Just in case you're wondering how you can set multiple different sizes in the same textview, but using an absolute size and not a relative one, you can achieve that using AbsoluteSizeSpan instead of a RelativeSizeSpan.

Just get the dimension in pixels of the desired text size

int textSize1 = getResources().getDimensionPixelSize(R.dimen.text_size_1);
int textSize2 = getResources().getDimensionPixelSize(R.dimen.text_size_2);

and then create a new AbsoluteSpan based on the text

String text1 = "Hi";
String text2 = "there";

SpannableString span1 = new SpannableString(text1);
span1.setSpan(new AbsoluteSizeSpan(textSize1), 0, text1.length(), SPAN_INCLUSIVE_INCLUSIVE);

SpannableString span2 = new SpannableString(text2);
span2.setSpan(new AbsoluteSizeSpan(textSize2), 0, text2.length(), SPAN_INCLUSIVE_INCLUSIVE);

// let's put both spans together with a separator and all
CharSequence finalText = TextUtils.concat(span1, " ", span2);
Johnny Five
  • 987
  • 1
  • 14
  • 29
Joao Sousa
  • 4,055
  • 1
  • 26
  • 29
10

You can get this done using html string and setting the html to Textview using
txtView.setText(Html.fromHtml("Your html string here"));

For example :

txtView.setText(Html.fromHtml("<html><body><font size=5 color=red>Hello </font> World </body><html>"));`
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
Remmyabhavan
  • 1,689
  • 5
  • 36
  • 65
  • 1
    Nice contribution! But fromHtml from now on (API >= N) is deprecated. For this to work do this to allow compatibility mode: **if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { txtView.setText(Html.fromHtml("your html string")), Html.FROM_HTML_MODE_LEGACY)); } else { txtView.setText(Html.fromHtml("your html string")); }** – statosdotcom Jul 01 '16 at 04:24
  • 1
    What is the unit of "5" ? Is it dp? Is it sp ? How can I change it to any of those? – android developer Apr 23 '20 at 11:28
  • 2
    colors and family works however, size doesn't work. – c-an Jul 29 '20 at 04:12
9
private SpannableStringBuilder SpannableStringBuilder(final String text, final char afterChar, final float reduceBy) {
        RelativeSizeSpan smallSizeText = new RelativeSizeSpan(reduceBy);
        SpannableStringBuilder ssBuilder = new SpannableStringBuilder(text);
        ssBuilder.setSpan(
                smallSizeText,
                text.indexOf(afterChar),
                text.length(),
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );

        return ssBuilder;
    }
------------------------
TextView textView =view.findViewById(R.id.textview);
String s= "123456.24";
textView.setText(SpannableStringBuilder(s, '.', 0.7f));

---------------- Result ---------------

Result :

12345.24

Community
  • 1
  • 1
Anandharaj R
  • 169
  • 1
  • 6
8

Method 1

public static void increaseFontSizeForPath(Spannable spannable, String path, float increaseTime) {
    int startIndexOfPath = spannable.toString().indexOf(path);
    spannable.setSpan(new RelativeSizeSpan(increaseTime), startIndexOfPath,
            startIndexOfPath + path.length(), 0);
}

using

Utils.increaseFontSizeForPath(spannable, "big", 3); // make "big" text bigger 3 time than normal text

enter image description here

Method 2

public static void setFontSizeForPath(Spannable spannable, String path, int fontSizeInPixel) {
    int startIndexOfPath = spannable.toString().indexOf(path);
    spannable.setSpan(new AbsoluteSizeSpan(fontSizeInPixel), startIndexOfPath,
            startIndexOfPath + path.length(), 0);
}

using

Utils.setFontSizeForPath(spannable, "big", (int) textView.getTextSize() + 20); // make "big" text bigger 20px than normal text

enter image description here

Linh
  • 57,942
  • 23
  • 262
  • 279
4

The best way to do that is Html without substring your text and fully dynamique For example :

  public static String getTextSize(String text,int size) {
         return "<span style=\"size:"+size+"\" >"+text+"</span>";

    }

and you can use color attribut etc... if the other hand :

size.setText(Html.fromHtml(getTextSize(ls.numProducts,100) + " " + mContext.getString(R.string.products));  
RaffMag
  • 114
  • 5
3

Try spannableStringbuilder. Using this we can create string with multiple font sizes.

PgmFreek
  • 6,374
  • 3
  • 36
  • 47
2

I have written my own function which takes 2 strings and 1 int (text size)

The full text and the part of the text you want to change the size of it.

It returns a SpannableStringBuilder which you can use it in text view.

  public static SpannableStringBuilder setSectionOfTextSize(String text, String textToChangeSize, int size){

        SpannableStringBuilder builder=new SpannableStringBuilder();

        if(textToChangeSize.length() > 0 && !textToChangeSize.trim().equals("")){

            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textToChangeSize.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();
            //for counting start/end indexes

            if(startingIndex < 0 || endingIndex <0){
                return builder.append(text);
            }
            else if(startingIndex >= 0 && endingIndex >=0){

                builder.append(text);
                builder.setSpan(new AbsoluteSizeSpan(size, true), startingIndex, endingIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }else{
            return builder.append(text);
        }

        return builder;
    }
Ali Asadi
  • 987
  • 10
  • 13
2

Utils method for kotlin lover

fun String.setFontSizeForPath(path: String, fontSizeInPixel: Int, colorCode: String = "#FF0000"): SpannableString {
    val spannable = SpannableString(this)
    val startIndexOfPath = spannable.toString().indexOf(path)
    spannable.setSpan(
        AbsoluteSizeSpan(fontSizeInPixel),
        startIndexOfPath,
        startIndexOfPath + path.length,
        0
    )
    spannable.setSpan(
        ForegroundColorSpan(Color.parseColor(colorCode)),
        startIndexOfPath,
        startIndexOfPath + path.length,
        0
    )

    return spannable
}

Use

text_view.text = "A B C D".setFontSizeForPath("B",30)
code4rox
  • 941
  • 9
  • 34
1
private SpannableString getFormattedText(String textToBold, String normalText, boolean boldTextFirst) {
    String result = boldTextFirst ? textToBold + normalText : normalText + textToBold;
    SpannableString str = new SpannableString(result);

    Typeface typeface = ResourcesCompat.getFont(requireContext(), R.font.product_sans_bold);
    int style = typeface != null ? typeface.getStyle() : Typeface.BOLD;

    int textToBoldStartIndex = str.toString().indexOf(textToBold);
    str.setSpan(new StyleSpan(style), textToBoldStartIndex, textToBoldStartIndex + textToBold.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    int normalTextStartIndex = str.toString().indexOf(normalText);
    str.setSpan(new AbsoluteSizeSpan(13, true), normalTextStartIndex, normalTextStartIndex + normalText.length(), 0);
    return str;
}
Dremo
  • 11
  • 2
1

Kotlin version on @Anandharaj R answer.

class SpannableStringBuilderHelper {

companion object {

    fun reduceTextSizeAfterChar(text: String, afterChar: Char, reduceBy: Float): SpannableStringBuilder? {
        val smallSizeText = RelativeSizeSpan(reduceBy)
        val ssBuilder = SpannableStringBuilder(text)
        ssBuilder.setSpan(
            smallSizeText,
            text.indexOf(afterChar),
            text.length,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        return ssBuilder
    }
}

}

Usage:

SpannableStringBuilderHelper.reduceTextSizeAfterChar("70/100", '/', 0.7f)
Hamid Reza
  • 624
  • 7
  • 23
0

In case you want to avoid too much confusion for your translators, I've come up with a way to have just a placeholder in the strings, which will be handled in code.

So, supposed you have this in the strings:

    <string name="test">
        <![CDATA[
        We found %1$s items]]>
    </string>

And you want the placeholder text to have a different size and color, you can use this:

        val textToPutAsPlaceHolder = "123"
        val formattedStr = getString(R.string.test, "$textToPutAsPlaceHolder<bc/>")
        val placeHolderTextSize = resources.getDimensionPixelSize(R.dimen.some_text_size)
        val placeHolderTextColor = ContextCompat.getColor(this, R.color.design_default_color_primary_dark)
        val textToShow = HtmlCompat.fromHtml(formattedStr, HtmlCompat.FROM_HTML_MODE_LEGACY, null, object : Html.TagHandler {
            var start = 0
            override fun handleTag(opening: Boolean, tag: String, output: Editable, xmlReader: XMLReader) {
                when (tag) {
                    "bc" -> if (!opening) start = output.length - textToPutAsPlaceHolder.length
                    "html" -> if (!opening) {
                        output.setSpan(AbsoluteSizeSpan(placeHolderTextSize), start, start + textToPutAsPlaceHolder.length, 0)
                        output.setSpan(ForegroundColorSpan(placeHolderTextColor), start, start + textToPutAsPlaceHolder.length, 0)
                    }
                }
            }
        })
        textView.text = textToShow

And the result:

enter image description here

android developer
  • 114,585
  • 152
  • 739
  • 1,270
-3

in kotlin do it as below by using html

HtmlCompat.fromHtml("<html><body><h1>This is Large Heading :-</h1><br>This is normal size<body></html>",HtmlCompat.FROM_HTML_MODE_LEGACY)
Shashank Pandey
  • 683
  • 6
  • 14