从源代码的 res/values/dimension.xml 加载维度值

Posted

技术标签:

【中文标题】从源代码的 res/values/dimension.xml 加载维度值【英文标题】:Load dimension value from res/values/dimension.xml from source code 【发布时间】:2012-06-22 16:14:11 【问题描述】:

我想按原样加载值。 我有两个dimension.xml 文件,一个在/res/values/dimension.xml 中,另一个在/res/values-sw360dp/dimension.xml 中。

从源代码我想做一些类似的事情

getResources().getDimension(R.dimen.tutorial_cross_marginTop);

这可行,但我得到的值乘以屏幕密度因子(hdpi 为 1.5,xhdpi 为 2.0 等)。

我也试过了

getResources().getString(R.dimen.tutorial_cross_marginTop);

这原则上可行,但我得到一个以“dip”结尾的字符串...

【问题讨论】:

我想知道这是否是 android 中的错误,因为 Resources 有方法 getDimensionPixelSize(int id) 准确地指出它以像素返回,所以 getDimension(int id) 应该以 dp(依赖独立单元)返回,这已经准备好了供使用,例如查看setPadding 【参考方案1】:

在我的dimens.xml 中有

<dimen name="test">48dp</dimen>

在代码中如果我这样做

int valueInPixels = (int) getResources().getDimension(R.dimen.test)

这将返回 72,因为文档状态乘以当前手机的密度(在我的情况下为 48dp x 1.5)

正如文档所述:

检索特定资源 ID 的维度。单位换算 基于与资源关联的当前 DisplayMetrics。

所以如果你想要精确的 dp 值,就像在 xml 中一样,只需将其除以 DisplayMetrics 密度

int dp = (int) (getResources().getDimension(R.dimen.test) / getResources().getDisplayMetrics().density);

dp 现在是 48

【讨论】:

我认为这里的文档特别不清楚。 “单位转换基于与资源关联的当前 DisplayMetrics。”当他们只想说他们转换为像素时。 如果您实际上要放弃显示指标乘数,您也可以只以 px 为单位定义您的维度。 48px。 getDimension(R.dimen.test) 将返回 48。 不适合我:***.com/questions/55972518/… @Trilarion 不过,它们不会简单地转换为像素。他们说dp 将给出相对于用于检索它的资源对象的比例的缩放像素值。一旦您进入各种获取资源的方式,这将更加相关。为简单起见,您可以将其视为相对于屏幕比例。还有sp,或相对于系统文本大小的像素,以及px,或直接像素。每个都是不同的,有不同的目的。 如果你想从dimens.xml获取sp值,那么你需要int sp = (int) (getResources().getDimension(R.dimen.test) / getResources().getDisplayMetrics() .scaledDensity)【参考方案2】:
Context.getResources().getDimension(int id);

【讨论】:

【参考方案3】:

Resource 类还有一个方法 getDimensionPixelSize(),我认为它可以满足您的需求。

【讨论】:

这是错误的! getDimensionPixelSize() 中也确实发生了指标转换,如果您可以参考它明确声明 Returns Resource dimension value multiplied by the appropriate metric and truncated to integer pixels. 的文档 这是错误的。指标转换也使用此方法进行。【参考方案4】:

对于那些只需要在资源中保存一些int 值的人,您可以执行以下操作。

整数.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="default_value">100</integer>
</resources> 

代码

int defaultValue = getResources().getInteger(R.integer.default_value);

【讨论】:

谢谢你,这是我正在寻找的更多内容,尽管可能不是其他人,但提供的这个解决方案实际上让我对我的代码的其他领域有了一些了解【参考方案5】:

您可以使用 getDimensionPixelOffset() 代替 getDimension,因此您不必强制转换为 int。

int valueInPixels = getResources().getDimensionPixelOffset(R.dimen.test)

【讨论】:

【参考方案6】:

使用 Kotlin 扩展

您可以添加扩展程序来简化此过程。它使您只需调用context.dp(R.dimen. tutorial_cross_marginTop) 即可获取浮点值

fun Context.px(@DimenRes dimen: Int): Int = resources.getDimension(dimen).toInt()

fun Context.dp(@DimenRes dimen: Int): Float = px(dimen) / resources.displayMetrics.density

如果你想在没有上下文的情况下处理它,你可以使用Resources.getSystem():

val Int.dp get() = this / Resources.getSystem().displayMetrics.density // Float

val Int.px get() = (this * Resources.getSystem().displayMetrics.density).toInt()

例如,在 xhdpi 设备上,使用 24.dp 获取 12.0 或使用 12.px 获取 24

【讨论】:

【参考方案7】:

您也可以在 xml 文件中写入整数.. 你见过这个吗] http://developer.android.com/guide/topics/resources/more-resources.html#Integer ? 用作。

 context.getResources().getInteger(R.integer.height_pop);

【讨论】:

【参考方案8】:
    This works but the value I get is multiplied times the screen density factor
  (1.5 for hdpi, 2.0 for xhdpi, etc).

我认为根据分辨率获取值很好,但如果您不想这样做,请以 px 为单位......

与密度无关的像素 (dp)

定义 UI 布局时应使用的虚拟像素单位,以与密度无关的方式表示布局尺寸或位置。 与密度无关的像素相当于 160 dpi 屏幕上的一个物理像素,这是系统为“中等”密度屏幕假定的基线密度。在运行时,系统会根据需要透明地处理 dp 单位的任何缩放,based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. 在定义应用程序的 UI 时,您应该始终使用 dp 单位,以确保您的 UI 在不同密度的屏幕上正确显示。

我认为根据分辨率更改值很好,但如果您不想这样做,请以 px 为单位......

参考这个link

按照这个

dp

与密度无关的像素 - 基于屏幕物理密度的抽象单位。这些单位是相对于 160 dpi(每英寸点数)的屏幕而言的,在该屏幕上 1dp 大致等于 1px。 When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. dp与像素的比例会随着屏幕密度的变化而变化,但不一定成正比。使用 dp 单位(而不是 px 单位)是一种简单的解决方案,可以使布局中的视图尺寸针对不同的屏幕密度正确调整大小。换言之,它为您的 UI 元素在不同设备上的真实尺寸提供了一致性。

像素

像素 - 对应于屏幕上的实际像素。不推荐使用此度量单位,因为实际表示可能因设备而异;每个设备每英寸的像素数可能不同,并且屏幕上的可用总像素数可能更多或更少。

【讨论】:

【参考方案9】:

如果您只想动态更改字体大小,那么您可以:

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.tutorial_cross_marginTop))

作为@achie 的回答,您可以像这样从dimens.xml 获取dp:

val dpValue = (resources.getDimension(R.dimen.tutorial_cross_marginTop)/ resources.displayMetrics.density).toInt()

或者像这样得到sp

val spValue = (resources.getDimension(R.dimen.font_size)/ resources.displayMetrics.scaledDensity).toInt()

关于 Resources.java #getDimension

    /**
     * Retrieve a dimensional for a particular resource ID.  Unit 
     * conversions are based on the current @link DisplayMetrics associated
     * with the resources.
     * 
     * @param id The desired resource identifier, as generated by the aapt
     *           tool. This integer encodes the package, type, and resource
     *           entry. The value 0 is an invalid identifier.
     * 
     * @return Resource dimension value multiplied by the appropriate 
     * metric.
     * 
     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
     *
     * @see #getDimensionPixelOffset
     * @see #getDimensionPixelSize
     */

资源维度值乘以相应的

【讨论】:

【参考方案10】:

这里有一个更好的解决方案,不涉及从 dp 到 px 再从 px 到 dp 的双重转换:

在 Kotlin 中

fun Resources.getRawDimensionInDp(@DimenRes dimenResId: Int): Float 
    val value = TypedValue()
    getValue(dimenResId, value, true)
    return TypedValue.complexToFloat(value.data)

// Usage: 
resources.getRawDimensionInDp(R.dimen.my_dimen_id)

在 Java 中

public class ResourcesUtil 
    static Float getRawDimensionInDp(Resources resources, @DimenRes int dimenResId) 
        TypedValue value = new TypedValue();
        resources.getValue(dimenResId, value, true);
        return TypedValue.complexToFloat(value.data);
    


// Usage: 
ResourcesUtil.getRawDimensionInDp(resources, R.dimen.my_dimen_id);

【讨论】:

以上是关于从源代码的 res/values/dimension.xml 加载维度值的主要内容,如果未能解决你的问题,请参考以下文章

如何从源代码安装 Grails 插件?

Android View体系从源代码解析View的layout和draw流程

从 Ubuntu 中的 pip install 包中找到源代码

从 NIB 与从代码加载自定义滑块:从代码加载时不存在子视图

为啥 PyCharm 不导入/检测从源代码编译和安装的 OpenCV?

从官方未修改的源代码编译 android 内核会导致损坏的结果