DisplayMetrics.scaledDensity在Android中实际返回了什么?

nib*_*ius 6 android

我正在尝试了解Android中的sp单元,但我无法弄清楚它是如何工作的.该文件说:

SP

与比例无关的像素 - 这与dp单位类似,但它也可以通过用户的字体大小首选项进行缩放.建议您在指定字体大小时使用此单位,以便根据屏幕密度和用户偏好调整它们.

使用DisplayMetrics可以获得scaledDensity,它是:

显示屏上显示的字体的缩放系数.这与密度相同,除了它可以在运行时根据用户对字体大小的偏好以较小的增量进行调整.

因此,鉴于此信息,我假设scaledDensity将随着我更改系统字体大小而改变,并且我可以使用此信息来了解1dp和1sp(scaledDensity / density)之间的比率.

然而,当我在手机(Nexus 4)上测试时,我没有得到我期待的结果.DisplayMetrics.scaledDensity始终返回相同的值(等于DisplayMetrics.density),无论我将手机设置为使用什么字体大小(通过settings -> accessibility -> use large fontsettings -> display -> font size).

当我更改字体设置时,我指定的字体会改变大小,因此sp单元按预期工作,但scaledDensity值根本不会改变.

我用来获取scaledDensity的代码是:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.scaledDensity
Run Code Online (Sandbox Code Playgroud)

我做错了什么或者我误解了DisplayMetrics.scaledDensity实际上做了什么?

更新

这是三个屏幕截图,说明了我的意思:

在此输入图像描述

这是应用程序的代码:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

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(android.util.TypedValue. COMPLEX_UNIT_SP , 24);
((TextView) this.findViewById(R.id.dp )).setTextSize(android.util.TypedValue. COMPLEX_UNIT_DIP, 24);
Run Code Online (Sandbox Code Playgroud)

我希望能够计算绘制某个字符串所需的像素数量.如果我使用dp指定字符串的大小,我可以很容易地计算所需的像素displayMetrics.density.但是,当我使用sp并尝试计算像素数量时,displayMetrics.scaledDensity我没有得到正确的值.

nib*_*ius 13

我自己能够弄清楚这一点.挖线槽Android源代码之后,我发现,该scaledDensity属性被计算为scaledDensity = density * fontScale,其中fontScale取决于系统设置为字体大小.所以这就像我认为的那样.

scaledDensity无论字体大小如何,我总是拥有相同值的原因是因为我使用DisplayMetrics来显示错误的显示.我从默认显示中获得了DisplayMetrics,关于此文档说:

返回此WindowManager实例将在其上创建新窗口的Display.

尽管此方法的名称,返回的显示不一定是系统的主显示(请参阅DEFAULT_DISPLAY).返回的显示可以是该窗口管理器实例正在管理的辅助显示.可以将其视为此WindowManager实例默认使用的显示.

在这种情况下,默认显示与系统的主显示不同显示,因此当我更改系统字体设置时,在主显示屏上而不是在默认显示屏上更改设置.如果我更新我的代码以获取DisplayMetrics实际使用的显示,则scaledDensity返回根据系统字体设置缩放的预期值.

使用以下更新的代码,使用getResources().getDisplayMetrics()一切按预期工作:

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);
Run Code Online (Sandbox Code Playgroud)

通过这种获取显示度量的方式,这是我得到的结果(观察缩放密度如何随字体大小而变化):

在此输入图像描述