开发者

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

开发者 https://www.devze.com 2023-01-15 10:20 出处:网络
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.

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?


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


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


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

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);


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>


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


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


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消