getDimension,getDimensionPixelOffset和getDimensionPixelSize的区别

236 阅读3分钟

方法getDimension, getDimensionPixelOffset, 和 getDimensionPixelSize都是用于从资源文件 dimens.xmldimen.xml 中检索指定资源ID的尺寸值, 并转换成像素(px),但它们在处理所检索的尺寸值时各有不同:

getDimension(@DimenRes int id)

  • 目的: 检索资源ID指定的尺寸值。这个方法返回的是原始尺寸值乘以当前DisplayMetrics关联的像素密度(density)后的结果。
  • 返回类型: float。返回值是一个浮点数,提供更精确的尺寸值,适用于需要高精度的场景。

getDimensionPixelOffset(@DimenRes int id)

  • 目的: 与getDimension相似,用于检索特定资源ID的尺寸值。不同之处在于,它将返回的值转换为整数像素,并且转换过程中直接截断(舍去)小数部分。
  • 返回类型: int。返回值是一个整数,表示以像素为单位的尺寸。

getDimensionPixelSize(@DimenRes int id)

  • 目的: 与getDimension相似,用于检索特定资源ID的尺寸值。它将浮点数四舍五入到最近的整数,并确保非零的基值小于或等于一个像素大小。

  • 返回类型: int。同样返回一个整数,表示以像素为单位的尺寸,但是它保证了至少有一个像素的大小。

    假设 getResource().getDisplayMetrics().density = 1, 经过方法getDimensionPixelSize(@DimenRes int id)的转换如下:

2.3dp -> 2px
2.5dp -> 3px
2.7dp -> 3px
0.3dp -> 1px

总结:这三个方法的主要区别在于它们如何处理原始的浮点维度值。getDimension提供最精确的值(浮点数),getDimensionPixelOffset通过截断小数部分提供一个粗略的整数值,而getDimensionPixelSize通过四舍五入,并保证非零值至少为1像素,提供一个更为实用的整数值。选择哪个方法取决于特定场景下对尺寸精度的需求。

源码如下:

/**
 * 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
 */
public float getDimension(@DimenRes int id) throws NotFoundException {
    final TypedValue value = obtainTempTypedValue();
    try {
        final ResourcesImpl impl = mResourcesImpl;
        impl.getValue(id, value, true);
        if (value.type == TypedValue.TYPE_DIMENSION) {
            return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
        }
        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                + " type #0x" + Integer.toHexString(value.type) + " is not valid");
    } finally {
        releaseTempTypedValue(value);
    }
}

/**
 * Retrieve a dimensional for a particular resource ID for use
 * as an offset in raw pixels.  This is the same as
 * {@link #getDimension}, except the returned value is converted to
 * integer pixels for you.  An offset conversion involves simply
 * truncating the base value to an integer.
 * 
 * @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 and truncated to integer pixels.
 * 
 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
 *
 * @see #getDimension
 * @see #getDimensionPixelSize
 */
public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
    final TypedValue value = obtainTempTypedValue();
    try {
        final ResourcesImpl impl = mResourcesImpl;
        impl.getValue(id, value, true);
        if (value.type == TypedValue.TYPE_DIMENSION) {
            return TypedValue.complexToDimensionPixelOffset(value.data,
                    impl.getDisplayMetrics());
        }
        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                + " type #0x" + Integer.toHexString(value.type) + " is not valid");
    } finally {
        releaseTempTypedValue(value);
    }
}

/**
 * Retrieve a dimensional for a particular resource ID for use
 * as a size in raw pixels.  This is the same as
 * {@link #getDimension}, except the returned value is converted to
 * integer pixels for use as a size.  A size conversion involves
 * rounding the base value, and ensuring that a non-zero base value
 * is at least one pixel in size.
 * 
 * @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 and truncated to integer pixels.
 *  
 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
 *
 * @see #getDimension
 * @see #getDimensionPixelOffset
 */
public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
    final TypedValue value = obtainTempTypedValue();
    try {
        final ResourcesImpl impl = mResourcesImpl;
        impl.getValue(id, value, true);
        if (value.type == TypedValue.TYPE_DIMENSION) {
            return TypedValue.complexToDimensionPixelSize(value.data, impl.getDisplayMetrics());
        }
        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                + " type #0x" + Integer.toHexString(value.type) + " is not valid");
    } finally {
        releaseTempTypedValue(value);
    }
}