将 dp(density-independent pixels)转换为 px(pixels)是 Android 开发中的一个常见需求。为了实现一个详细且兼容性良好的 dp 到 px 的转换方法,可以使用以下步骤:

  1. 获取屏幕密度:通过 Resources.getDisplayMetrics().density 获取当前设备的屏幕密度。
  2. 转换公式:使用 px = dp * (densityDpi / 160) 公式进行转换,densityDpi / 160 也就是 density。
  3. 考虑四舍五入:为了确保转换后的值是一个整数,可以使用 Math.round 方法。

下面是一个完整的实现,考虑了各种兼容情况:

import android.content.Context;
import android.util.DisplayMetrics;

public class Utils {

    /**
     * 将 dp 转换为 px
     *
     * @param context 应用程序上下文
     * @param dpValue dp 值
     * @return px 值
     */
    public static int dpToPx(Context context, float dpValue) {
        // 获取屏幕密度
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        float density = metrics.density;
        // dp 转换为 px,并进行四舍五入
        return Math.round(dpValue * density);
    }

    /**
     * 将 px 转换为 dp
     *
     * @param context 应用程序上下文
     * @param pxValue px 值
     * @return dp 值
     */
    public static int pxToDp(Context context, float pxValue) {
        // 获取屏幕密度
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        float density = metrics.density;
        // px 转换为 dp,并进行四舍五入
        return Math.round(pxValue / density);
    }
}

详细说明

  1. 获取屏幕密度

    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float density = metrics.density;
    

    这里通过 getDisplayMetrics 方法获取设备的 DisplayMetrics 对象,从中提取 density 属性,该属性表示屏幕的逻辑密度。

  2. dp 转 px 转换公式

    return Math.round(dpValue * density);
    

    使用 Math.round 方法对结果进行四舍五入,确保转换后的 px 值是一个整数。

  3. px 转 dp 转换公式

    return Math.round(pxValue / density);
    

    同样使用 Math.round 方法对结果进行四舍五入,确保转换后的 dp 值是一个整数。

兼容性考虑

  • 设备适配:使用 Resources.getDisplayMetrics() 可以确保适配各种设备的屏幕密度。
  • 四舍五入:使用 Math.round 方法可以确保转换后的值更加精确,避免因浮点数转换引起的误差。
  • 上下文获取:通过 Context 获取 Resources 对象,确保在不同组件中(如 ActivityFragmentService 等)都可以使用这个方法。

使用示例

在你的 Activity 或 Fragment 中,可以这样使用这个工具类:

int pxValue = Utils.dpToPx(this, 16);  // 将 16dp 转换为 px
int dpValue = Utils.pxToDp(this, 48);  // 将 48px 转换为 dp

通过这种方式,你可以在项目中轻松地进行 dp 和 px 之间的转换,确保在不同屏幕密度下都能得到正确的结果。

为什么 densityDpi 除以160

基准屏幕密度(160 dpi)

  • 在 Android 中,160 dpi 被定义为基准屏幕密度(也称为中等密度屏幕,mdpi)。1 dp 等于 1 px 在这种密度下。
  • 基于 160 dpi 的基准,其他屏幕密度都是相对于它的倍数或分数。例如:
    • 低密度屏幕(ldpi)是 120 dpi
    • 高密度屏幕(hdpi)是 240 dpi
    • 超高密度屏幕(xhdpi)是 320 dpi
    • 超超高密度屏幕(xxhdpi)是 480 dpi
    • 超超超高密度屏幕(xxxhdpi)是 640 dpi

density 和 densityDpi 有什么区别

density

  • 定义density 是一个表示屏幕密度的相对度量,是逻辑像素(dp)与物理像素(px)之间的比例因子。
  • 类型float
  • 范围:通常取值为 0.75(ldpi)、1.0(mdpi)、1.5(hdpi)、2.0(xhdpi)、3.0(xxhdpi)、4.0(xxxhdpi)等。
  • 用途:用于在代码中方便地将 dp 单位转换为 px 单位。通过 density 属性,可以方便地处理与屏幕密度相关的计算。

densityDpi

  • 定义densityDpi 是屏幕的实际像素密度,表示每英寸包含的像素点数(dpi:dots per inch)。
  • 类型int
  • 范围:常见的值包括 120(ldpi)、160(mdpi)、240(hdpi)、320(xhdpi)、480(xxhdpi)、640(xxxhdpi)等。
  • 用途:用于描述屏幕的物理像素密度,通常在需要精确处理图像分辨率或调整资源时使用。

关系和转换

densitydensityDpi 之间有直接的关系:

  • density = densityDpi / 160

这里的 160 是 Android 定义的基准密度(mdpi),表示每英寸有 160 个像素。