What does DisplayMetrics.scaledDensity actually return in Android?

后端 未结 2 787
野的像风
野的像风 2021-02-06 12:32

I\'m trying to understand the sp unit in Android, but I can\'t really figure out how it works. The documentation say:

sp

Scale-independent Pi

相关标签:
2条回答
  • 2021-02-06 12:45

    I was able to figure out this myself. After digging trough the Android source code I found that the scaledDensity property is calculated as scaledDensity = density * fontScale where fontScale depends on the system setting for font size. So this was just as I thought it should be.

    The reason why scaledDensity always had the same value for me regardless of font size was because I was using the DisplayMetrics for the wrong Display. I got the DisplayMetrics from the default display and regarding this the documentation say:

    Returns the Display upon which this WindowManager instance will create new windows.

    Despite the name of this method, the display that is returned is not necessarily the primary display of the system (see DEFAULT_DISPLAY). The returned display could instead be a secondary display that this window manager instance is managing. Think of it as the display that this WindowManager instance uses by default.

    In this case the default display is not the same display as the primary display of the system, so when I change the system font setting that setting is changed on the primary display and not on the default display. If I update my code to get the DisplayMetrics for the display that is actually used scaledDensity returns the expected values scaled according to the system font settings.

    With the following updated code that uses getResources().getDisplayMetrics() everything works as expected:

    DisplayMetrics metrics = getResources().getDisplayMetrics();
    String result = "\n"
        + "density : " + metrics.density + " (24 dp = " + 24 * metrics.density + " px)\n"
        + "scaledDensity: " + metrics.scaledDensity + " (24 sp = " + 24 * metrics.scaledDensity + " px)\n" ;
    
    ((TextView) this.findViewById(R.id.label)).setText(result);
    ((TextView) this.findViewById(R.id.sp)).setTextSize(TypedValue.COMPLEX_UNIT_SP, 24);
    ((TextView) this.findViewById(R.id.dp)).setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24);
    

    With this way of getting the display metrics this is the result I get (observe how the scaled density changes with font size):

    enter image description here

    0 讨论(0)
  • 2021-02-06 12:59

    Scaled density is a unit of measurement not a value of font-size. Let me try to give you an example, feel free to follow up with a comment if you would like more explanation.

    Say you have a font size 18sp. This needs to get converted to pixels in order to display on the screen. The following calculation is made: pixels = fontSize * scaledDensity * scale. Now, when you change your phone's settings, you are changing the scale. This results in the same calculation being made, but let's say with a scale of 1.5 now instead of 1. The unit of scaledDensity is not changed because your screen's pixel density has not changed.

    I hope that helps!

    0 讨论(0)
提交回复
热议问题