131

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?

Cœur
  • 37,241
  • 25
  • 195
  • 267
singhspk
  • 2,389
  • 3
  • 23
  • 28

8 Answers8

380

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
Todd Painton
  • 701
  • 7
  • 20
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • I just found that and was about to post it here. Thanks a lot! – singhspk Sep 10 '10 at 18:54
  • No problem! :) It was good for me to learn too, haha. Strange there's no way to return different values, but I'm sure it's an easy conversion if I looked into it. – Kevin Coppock Sep 10 '10 at 19:00
  • 1
    I think it should actually by TypedValue (singular). The import is android.util.TypedValue; – Hein du Plessis Mar 22 '11 at 08:43
  • 5
    Also to note, it only started doing this at API level 7. Another "gotcha" in a ridiculous API. – mxcl Feb 11 '12 at 21:10
  • 3
    Important to watch out for the argument order - I accidentally had setTextSize(size, TypedValue.COMPLEX_UNIT_SP) because that was the order I mistakenly presumed! – Mark Jul 24 '12 at 04:01
  • @MarkCarter Heh, I did the same thing one time and debugged it for an hour or two before realizing... >.> – Kevin Coppock Jul 24 '12 at 04:09
  • 1
    Interestingly, on ICS on my Galaxy Nexus, using setTextSize(14, TypedValue.COMPLEX_UNIT_SP) made no effect (so used default size), but when I upgraded to Jelly Bean, none of the text was displayed (like 0 size). I was just about to report a Jelly Bean bug when I realised my mistake! – Mark Jul 24 '12 at 05:45
  • An inconsistency to watch out for is that in setting text size in paint objects, e.g. paintText.setTextSize(size), the default is actual pixel size, so you have to use paintText.setTextSize(size*dpi). – Androidcoder Aug 20 '15 at 14:00
21

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 :)

M_AWADI
  • 4,086
  • 1
  • 18
  • 12
8

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

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
6

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>
NagarjunaReddy
  • 8,621
  • 10
  • 63
  • 98
5

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));
ranjan
  • 136
  • 1
  • 12
4

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

Frank Nguyen
  • 6,493
  • 3
  • 38
  • 37
3

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))
    }
Gibolt
  • 42,564
  • 15
  • 187
  • 127
0

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.

Kevin Grant
  • 2,311
  • 23
  • 17