getDimension()/getDimensionPixelSize() - mutliplier issue

回眸只為那壹抹淺笑 提交于 2019-12-20 19:26:19

问题


So I have android 2.3.5 device which is NORMAL/HDPI. I have a dimens.xml in my project:

...
    <dimen name="gameresult_congrats_label_msg_textSize">20sp</dimen>
...

this file is absolutely identical in values-normal/values-hdpi and so on folders. In my first activity app shows me that value using:

Toast.makeText(this, "textSize is "+getResources().getDimensionPixelSize(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();

and it displays 30. I Tried also:

Toast.makeText(this, "textSize is "+getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();

but result is the same. But only when I tried this:

Toast.makeText(this, "textSize is "+getResources().getString(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();

I got my "20sp" finally! But why is that? Official docs says that those methods returns

Resource dimension value multiplied by the appropriate metric.

I checked this by changing my value to 25 and I got 38 which means aos uses 1.5 multiplier. But why? It already gets value from appropriate folder which means it gets a ready to use value! From where aos gets that 1.5x multiplier? I know it depends on DisplayMetrics. But how it calculates 1.5x?
UPDATE
I understand about multiplier but, you see, the real problem here is about double scaling. And thats why I did asked this question.
So if I have some layout.xml (in res\layout folder) with TexView defined like:

<TextView
    android:id="@+id/congratsLabel"
    ...
    android:textSize="@dimen/gameresult_congrats_label_msg_textSize" />

Everything looks ok. I mean textview is like Im expecting.
Now lets do the same in code:

TextView congratsLabel = fineViewById(R.id.congratsLabel); 
textSize = getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize)
congratsLabel.setTextSize(textSize) 

and here is the issue!!! getResources().getDimension() returns a SCALED value and thats ok. But the resulting size of my textView will be 1.5 greater than I expecting cuz setTextSize works with SP and here comes the second scale! And thats why AOS makes resulting text size scaled to 45 (originally defined as 20sp).


回答1:


Per the Supporting Different Screen Densities training, hdpi is 1.5x normal (mdpi) sizes. As getDimensionPixelSize takes this difference into account when converting into pixels, the returned value will be 1.5x your value in sp.

Note that sp is also dependent on the user's preferred text size and can therefore change to be even larger than 1.5x your expected value.




回答2:


Just to clarify (information obtained by inspecting Android source code):

Resources.getDimension() and getDimensionPixelOffset()/getDimensionPixelSize() differ only in that the former returns float while the latter two return the same value rounded to int appropriately. For all of them, the return value is in raw pixels.

All three functions are implemented by calling Resources.getValue() and converting the thus obtained TypedValue by calling TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset() and TypedValue.complexToDimensionPixelSize(), respectively.

Therefore, if you want to obtain the "raw" value together with the unit specified in the XML source, call Resources.getValue() and use the methods of the TypedValue class.




回答3:


Method getDimension() converts dp or sp values into pixels based on current screen density. This is very useful as you don't have to do it on your own, when you want to set in Java width or text size (they accepts only pixels).

But if you need original sp or dp you could do "reverse engineering".

Step 1. Check current scale ratio (based on screen density):

float scaleRatio = getResources().getDisplayMetrics().density;

Step 2. Get dimension from dimens.xml

float dimenPix = getResources().getDimension(R.dimen.your_dimen_name);

Step 3. Do some math

float dimenOrginal = dimenPix/scaleRatio;

Remarks:

  • usually you need int for dimension methods (like setWidth()), so you have to convert float result to int for instance using Math.round()
  • more accurate result when rounding to int you could get using such formula (dimenPix-0.5f)/scaleRatio
  • in case of sp you could take also into account user preferences about text scale

Read more about dimensions in Android: http://android4beginners.com/2013/07/appendix-c-everything-about-sizes-and-dimensions-in-android/




回答4:


If someone else needs this :

To address the double scaling problem Stan show when using getDimensionPixelSize with TextView.setTextSize :

You can use the alternate version of setTextSize where you can specify the unit like this :

title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.title));



回答5:


Because... NORMAL is NOT hdpi...
Normal is mdpi (160dpi) = 1.0x.
hdpi (240dpi) is 1.5x.
xhdpi (320dpi) is 2.0x.
xxdpi (480dpi) is 3.0x.
xxxhdpi (640dpi) is 4.0x.
And (last, but not least) ldpi (120dpi) is 0.75x.



来源:https://stackoverflow.com/questions/16368937/getdimension-getdimensionpixelsize-mutliplier-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!