TextView.setTextSize behaves abnormally - How to set text size of textview dynamically for different screens

AndroidTextview

Android Problem Overview


Calling TextView.setTextSize() is working abnormally. Right after the call to setTextSize if we get a getTextSize its returning a much higher value that what we set it to earlier.

Here's what we're doing:

zoomControl.setOnZoomInClickListener(new OnClickListener() {
    public void onClick(View view) {
        float size = mViewShabad.getTextSize() + 1;
        textView.setTextSize(size);
    }
});

Has anyone seen this before?

Android Solutions


Solution 1 - Android

The difference here is that in the setTextSize(int size) method, the unit type by default is "sp" or "scaled pixels". This value will be a different pixel dimension for each screen density (ldpi, mdpi, hdpi).

getTextSize(), on the other hand, returns the actual pixel dimensions of the text.

You can use setTextSize(int unit, float size) to specify a unit type. The constant values for this can be found in the TypedValue class, but some of them are:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels

Solution 2 - Android

this problem happend because the getTextSize() method return the size in pixels depend on screen density ! to get the Actual TextSize use this :

DisplayMetrics metrics;
metrics = getApplicationContext().getResources().getDisplayMetrics();
float Textsize =myTextView.getTextSize()/metrics.density;
myTextView.setTextSize(Textsize+1);

i hope it solve it :)

Solution 3 - Android

if Setting change font size,something cause show error,you can do as:

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);

Solution 4 - Android

When we try to setText() programmitically problem with getTextSize(), returns value in px instead of sp/dp/dip and we know 1sp/dp=1.5px(screen size =240).

 titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*1.5f)); 

is working perfectly for me or we can use displaymatrix to px:sp/dp ratio then replace that value with 1.5f

means-> titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*your_sp_and_px_ratio_in_int f));

Solution 5 - Android

After long time struck this and finally solved like this

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
          getResources().getDimension(R.dimen.textsize));

create dimen folder like this res/values/dimensions.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <dimen name="textsize">8sp</dimen>

 </resources>

Solution 6 - Android

In short, if you want to zoom out your textsize

float size = mViewShabad.getTextSize()*1.1f;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

Because getTextSize() return UNIT_PX, then we should use UNIT_PX

Solution 7 - Android

Kotlin Solution

To set using a resource, just use this:

textView.setTextSize(COMPLEX_UNIT_PX, textView.resources.getDimension(R.dimen.my_text_size))

To do the same with a resource value, add this extension property to much more easily set your text size

textView.textSizeRes = R.dimen.my_text_size

var TextView.textSizeRes
    get() = textSize.toInt()
    set(@DimenRes textSizeRes) {
        setTextSize(COMPLEX_UNIT_PX, resources.getDimension(textSizeRes))
    }

Solution 8 - Android

Adding some extra flavor for this answer, as also ran into a bit of confusion. You should be able to drop this test into any @RunWith(AndroidJUnit4.class) test you have in your project (you'll also need to add the dimens to your dimens.xml).

Note: All these tests pass

@Test public void testScaledFontSizes() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    final Context context = InstrumentationRegistry.getTargetContext();

    Configuration configuration = context.getResources().getConfiguration();
    configuration.fontScale = 2.0f;
    configuration.densityDpi = 160; // mdpi, 1:1
    context.getResources().updateConfiguration(configuration, null);

    float scaledTextSize = context.getResources().getDimensionPixelSize(R.dimen.sp_15);
    assertEquals(30.0f, scaledTextSize);

    // Create a new TextView with the explicitly set configuration
    TextView textView = new TextView(context);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, scaledTextSize);

    // 30, because font size is scaled
    assertEquals(30.0f, textView.getTextSize());

    // This is what we *don't* want, it's scaled *twice*!
    textView.setTextSize(scaledTextSize);
    assertEquals(60.0f, textView.getTextSize());

    // DP instead of SP tests
    float fifteenDp = context.getResources().getDimensionPixelSize(R.dimen.dp_15);
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fifteenDp);
    // Still 15, because it's DP, not SP
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(fifteenDp);
    // 30, because setTextSize DOES font scaling
    assertEquals(30.0f, textView.getTextSize());
  }
}

The big takeaway I found is that TextView.setTextSize(float) applies the font scaling, so if you pass in a dimen thats already labelled as SP instead of DP, then it will receive the font scaling twice.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsinghspkView Question on Stackoverflow
Solution 1 - AndroidKevin CoppockView Answer on Stackoverflow
Solution 2 - AndroidM_AWADIView Answer on Stackoverflow
Solution 3 - Androidhui 谁与争辉View Answer on Stackoverflow
Solution 4 - AndroidranjanView Answer on Stackoverflow
Solution 5 - AndroidNagarjunaReddyView Answer on Stackoverflow
Solution 6 - AndroidFrank NguyenView Answer on Stackoverflow
Solution 7 - AndroidGiboltView Answer on Stackoverflow
Solution 8 - AndroidKevin GrantView Answer on Stackoverflow