21

所以我有 android 2.3.5 设备,它是 NORMAL/HDPI。我的项目中有一个dimens.xml:

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

此文件在 values-normal/values-hdpi 等文件夹中完全相同。在我的第一个活动应用程序中,使用以下方法向我展示了该值:

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

它显示 30。我也试过:

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

但结果是一样的。但只有当我尝试这个时:

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

我终于得到了我的“20sp”!但这是为什么呢?官方文档说这些方法返回

资源维度值乘以适当的指标。

我通过将值更改为 25 来检查这一点,我得到 38,这意味着 aos 使用 1.5 乘数。但为什么?它已经从适当的文件夹中获得了价值,这意味着它获得了可以使用的价值!aos 从哪里得到 1.5 倍的乘数?我知道这取决于 DisplayMetrics。但它是如何计算 1.5 倍的呢?
更新
我了解乘数,但你看,这里真正的问题是关于双倍缩放。这就是为什么我确实问了这个问题。
因此,如果我有一些 layout.xml(在 res\layout 文件夹中)的 TexView 定义如下:

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

一切看起来都很好。我的意思是 textview 就像我期待的那样。
现在让我们在代码中做同样的事情:

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

这是问题!getResources().getDimension() 返回一个SCALED值,没关系。但是我的 textView 的最终大小将比我预期的大 1.5,因为 setTextSize 与 SP 一起使用,第二个比例出现了!这就是 AOS 将生成的文本大小缩放为 45(最初定义为 20sp)的原因。

4

5 回答 5

28

只是为了澄清(通过检查Android源代码获得的信息):

Resources.getDimension()getDimensionPixelOffset()/getDimensionPixelSize()不同之处仅在于前者返回float,而后两者返回相同的值,四舍五入int。对于所有这些,返回值都是原始像素。

这三个函数都是通过调用和转换分别调用,和Resources.getValue()得到的来实现的。TypedValueTypedValue.complexToDimension()TypedValue.complexToDimensionPixelOffset()TypedValue.complexToDimensionPixelSize()

因此,如果要获取“原始”值以及 XML 源中指定的单位,请调用Resources.getValue()并使用TypedValue类的方法。

于 2014-09-01T15:55:39.693 回答
19

方法 getDimension() 根据当前屏幕密度将 dp 或 sp 值转换为像素。这非常有用,因为当您想设置 Java 宽度或文本大小(它们只接受像素)时,您不必自己做。

但是,如果您需要原始 sp 或 dp,您可以进行“逆向工程”。

步骤 1. 检查当前缩放比例(基于屏幕密度):

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

步骤 2. 从 dimens.xml 获取维度

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

第 3 步。做一些数学运算

float dimenOrginal = dimenPix/scaleRatio;

评论:

  • 通常你需要 int 作为维度方法(比如 setWidth()),所以你必须例如使用 Math.round() 将 float 结果转换为 int
  • 使用这样的公式 (dimenPix-0.5f)/scaleRatio 可以得到更准确的结果
  • 如果是 sp,您还可以考虑用户对文本比例的偏好

阅读有关 Android 尺寸的更多信息:http ://android4beginners.com/2013/07/appendix-c-everything-about-sizes-and-dimensions-in-android/

于 2013-07-06T11:49:34.710 回答
16

根据支持不同的屏幕密度培训,hdpi 是 1.5 倍正常 (mdpi) 大小。由于getDimensionPixelSize在转换为像素时考虑了这种差异,因此返回的值将是 .5 中值的 1.5 倍sp

请注意,这sp也取决于用户的首选文本大小,因此可以更改为甚至大于您预期值的 1.5 倍。

于 2013-05-03T23:33:44.257 回答
8

如果其他人需要这个:

为了解决 Stan show 在使用 getDimensionPixelSize 和 TextView.setTextSize 时出现的双重缩放问题:

您可以使用 setTextSize 的替代版本,您可以在其中指定单位,如下所示:

title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.title));
于 2014-04-09T13:23:51.903 回答
1

因为... NORMAL 不是 hdpi...
Normal 是 mdpi (160dpi) = 1.0x。
hdpi (240dpi) 是 1.5 倍。
xhdpi (320dpi) 为 2.0x。
xxdpi (480dpi) 为 3.0x。
xxxhdpi (640dpi) 为 4.0x。
并且(最后但并非最不重要的一点)ldpi (120dpi) 是 0.75x。

于 2013-10-14T16:08:31.673 回答