公式px到dp,dp到px android

时间:2011-11-29 10:38:16

标签: android formula density-independent-pixel

我正在尝试计算可变数量的像素到密度独立像素,反之亦然。

此公式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));不适用于小型设备,因为它除以零。

这是我的dp to px公式:

px = (int)(dp * (displayMetrics.densityDpi / 160));

有人可以给我一些指示吗?

20 个答案:

答案 0 :(得分:309)

注意:上面广泛使用的解决方案基于displayMetrics.density。但是,文档解释说这个值是一个舍入值,与屏幕“桶”一起使用。例如。在我的Nexus 10上,它返回2,其中实际值为298dpi(实际)/ 160dpi(默认值)= 1.8625。

根据您的要求,您可能需要完全转换,可以这样实现:

[编辑]这并不意味着与Android的内部dp单元混合,因为这当然仍然基于屏幕存储桶。如果您希望在不同设备上呈现相同实际大小的单位,请使用此选项。

将dp转换为像素:

public int dpToPx(int dp) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));     
}

将像素转换为dp:

public int pxToDp(int px) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

请注意,有xdpi和ydpi属性,您可能想要区分,但我无法想象这些值差别很大的理智显示。

答案 1 :(得分:101)

我使用以下公式解决了我的问题。愿其他人从中受益。

dp到px:

displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);

px to dp:

displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);

答案 2 :(得分:32)

px到dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());

答案 3 :(得分:27)

只需致电getResources().getDimensionPixelSize(R.dimen.your_dimension)即可将dp单位转换为像素

答案 4 :(得分:26)

高效的方式

DP to Pixel:

private int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

Pixel to DP:

private int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

希望这会对你有所帮助。

答案 5 :(得分:14)

使用此功能

private int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}

答案 6 :(得分:5)

px = dp * (dpi / 160)

dp = px * (160 / dpi)

答案 7 :(得分:3)

在大多数情况下,频繁调用转换函数。我们可以通过添加memoization来优化它。因此,它不会在每次调用函数时计算。

让我们声明一个HashMap,它将存储计算出的值。

private static Map<Float, Float> pxCache = new HashMap<>();

计算像素值的函数:

public static float calculateDpToPixel(float dp, Context context) {

        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * (metrics.densityDpi / 160f);
        return px;

    }

一个memoization函数,它从HashMap返回值并保留以前值的记录。

可以在Java中以不同方式实现记忆。 对于Java 7

public static float convertDpToPixel(float dp, final Context context) {

        Float f = pxCache.get(dp);
        if (f == null) {
            synchronized (pxCache) {
                f = calculateDpToPixel(dp, context);
                pxCache.put(dp, f);
            }

        }

        return f;
    }

Java 8支持Lambda函数

public static float convertDpToPixel(float dp, final Context context) {

        pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}

感谢。

答案 8 :(得分:2)

答案 9 :(得分:2)

以下功能在我的设备上运行良好。

取自constructing function calls

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}

答案 10 :(得分:1)

您可以使用[DisplayMatrics][1]并确定屏幕密度。像这样:

int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);

我记得最好使用地板进行偏移和舍入宽度。

答案 11 :(得分:1)

如果您正在寻找一个在线计算器,可以在不同的屏幕密度this is the most complete tool I know of下将DP,SP,英寸,毫米,点或像素相互转换。

答案 12 :(得分:1)

//用于获取Decimal / Float

public static float convertPixelsToDp(float px, Context context) {

    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}



public static float convertDpToPixel(float dp, Context context) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


// for  getting in terms of Integer

private int convertPxToDp(int px, Context context) {
    Resources resources = context.getResources();
    return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}


private int convertDpToPx(int dp, Context context) {
    Resources resources = context.getResources();

    return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));

}

<强> ------------------------------------------------------------------------

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


private int convertDpToPx(int dp){
    return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));

}

private int convertPxToDp(int px){
    return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}

答案 13 :(得分:0)

使用这些Kotlin扩展名:

/**
 * Converts Pixel to DP.
 */
val Int.pxToDp: Int
    get() = (this / Resources.getSystem().displayMetrics.density).toInt()

/**
 * Converts DP to Pixel.
 */
val Int.dpToPx: Int
    get() = (this * Resources.getSystem().displayMetrics.density).toInt()

答案 14 :(得分:0)

这是使用kotlin扩展名的另一种方法:

val Int.dpToPx: Int
    get() = Math.round(this * Resources.getSystem().displayMetrics.density)

val Int.pxToDp: Int
    get() = Math.round(this / Resources.getSystem().displayMetrics.density)

然后可以在任何地方像这样使用

12.dpToPx

244.pxToDp

答案 15 :(得分:0)

在其他答案的帮助下,我写了这个函数。

public static int convertToPixels(Context context, int nDP)
{
        final float conversionScale = context.getResources().getDisplayMetrics().density; 
        return (int) ((nDP * conversionScale) + 0.5f) ;
}

答案 16 :(得分:0)

ct_robs上的变化回答如上所述,如果使用整数,不仅可以避免除以0,还可以在小型设备上产生可用的结果:

在整数计算中,包括最大精度的除法,在除法之前先进行乘法,以减少截断效应。

px = dp * dpi / 160 dp = px * 160 / dpi

5 * 120 = 600/160 = 3

而不是

5 *(120/160 = 0)= 0

如果您想要舍入结果,请执行此操作

px =(10 * dp * dpi / 160 + 5)/ 10 dp =(10 * px * 160 / dpi + 5)/ 10

10 * 5 * 120 = 6000/160 = 37 + 5 = 42/10 = 4

答案 17 :(得分:0)

DisplayMetrics displayMetrics = contaxt.getResources()                 .getDisplayMetrics();

    int densityDpi = (int) (displayMetrics.density * 160f);
    int ratio = (densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    int px;
    if (ratio == 0) {
        px = dp;
    } else {
        px = Math.round(dp * ratio);

    }

答案 18 :(得分:0)

上面接受的答案并不完全准确。根据检查Android源代码获得的信息:

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

通过分别致电Resources.getValue()TypedValueTypedValue.complexToDimension()调用TypedValue.complexToDimensionPixelOffset()并转换由此获得的TypedValue.complexToDimensionPixelSize()来实现所有这三项功能。

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

答案 19 :(得分:0)

随意使用我写的这个方法:

int dpToPx(int dp)
{
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}