Android 公式px到dp,dp到px

Android 公式px到dp,dp到px,android,formula,density-independent-pixel,Android,Formula,Density Independent Pixel,我试图计算一个可变数量的像素到密度无关的像素,反之亦然 这个公式(px到dp):dp=(int)(px/(displayMetrics.densityDpi/160))在小型设备上不起作用,因为它被零除 这是我的dp到px公式: px = (int)(dp * (displayMetrics.densityDpi / 160)); 有人能给我一些指示吗?你可以使用[DisplayMatrics][1]来确定屏幕密度。大概是这样的: px = dp * (dpi / 160) dp = px

我试图计算一个可变数量的像素到密度无关的像素,反之亦然

这个公式
(px到dp):dp=(int)(px/(displayMetrics.densityDpi/160))在小型设备上不起作用,因为它被零除

这是我的dp到px公式:

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

有人能给我一些指示吗?

你可以使用
[DisplayMatrics][1]
来确定屏幕密度。大概是这样的:

px = dp * (dpi / 160)

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

正如我所记得的,最好使用地板进行偏移,并将宽度修成圆形。

px到dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());
private int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
试试这个

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

dp至px:

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

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

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

根据您的需求,您可能需要进行精确的转换,具体实现方式如下:

int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);
[编辑]这并不意味着要与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属性,您可能想加以区分,但我无法想象这些值有很大差异的正常显示。

请随意使用我编写的此方法:

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

只要调用
getResources().getDimensionPixelSize(R.dimen.your_dimension)
即可将单位从
dp
转换为像素

如果您正在寻找一个在线计算器,用于在不同屏幕密度下将dp、SP、英寸、毫米、点或像素相互转换,.

上述答案并不完全准确。根据查看Android源代码获得的信息:

Resources.getDimension()
getDimensionPixelOffset()
/
getDimensionPixelSize()
的不同之处在于前者返回
float
,而后两者返回相同的值,并相应地四舍五入到
int
。对于所有这些对象,返回值均以原始像素为单位

这三个函数都是通过调用
Resources.getValue()
实现的,并分别通过调用
TypedValue.complexToDimension()
TypedValue.complexToDimensionPixelOffset()
TypedValue.complexToDimensionPixelSize()
来转换由此获得的
TypedValue.complexToDimensionPixelSize()


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

在上面的ct_robs答案上的变体,如果您使用整数,不仅可以避免被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);

    }
在整数计算中,为了达到最高精度,需要先除法,然后再除法,以减少截断效应

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

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

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

private static Map<Float, Float> pxCache = new HashMap<>();
一种记忆函数,它从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;
    }
public static float convertDpToPixel(float dp, final Context context) {

        pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}
Java 8支持Lambda函数

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;
    }
public static float convertDpToPixel(float dp, final Context context) {

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

谢谢。

使用此功能

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

下面的功能在各种设备中对我都很有效

它是从


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

public static int convertToPixels(Context context, int nDP)
{
        final float conversionScale = context.getResources().getDisplayMetrics().density; 
        return (int) ((nDP * conversionScale) + 0.5f) ;
}
有效率的方法吗 DP到像素:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());
private int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
像素到DP:

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

希望这将对您有所帮助。

//

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));

}
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu强

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));
}

下面是使用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)
/**
 * 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()
然后它可以在任何地方像这样使用

12.dpToPx

244.pxToDp

使用以下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)
/**
 * 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()

将dp单位转换为像素单位@Bram:我认为你的公式很好。你怎么能得到一个零除法呢?displayMetrics.densityDpi将是120、160、240或320,而不是0。我同意@ct\u rob。displayMetrics.densityDpi/160最小值为0.75。你一定是在错误的地方对int进行了转换。不过,现在我想起来了……在Brams的原始公式中,怎么会有零的除法呢?displayMetrics.densityDpi将为120、160、240或320,永远不会为0。
(displayMetrics.densityDpi/160)
-此部件在小型设备上可以得到0,在那里它计算出例如
120/160
,两个值都是int,结果都是0。结果是
(int)(px/0)
。啊,你说得对。所以他所需要做的就是在他的公式中使用一个长的:160.0这个答案与上面的答案相似,因为DisplayMetrics.DENSITY\u默认值为160。但是您能告诉我们这里的DPI是多少吗?我们是如何计算的。@Vame 0.5的加法用于四舍五入到最接近的整数值。。将0.5相加,然后将计算结果转换为int,从而使其截断尾数,并将特征保留为正确的四舍五入整数值。这并不总是正确的。当我有两个布局,一个布局在另一个布局中,然后我将每个视图的角(一个使用dp,另一个转换为dp)圆角不匹配!我对这项技术没有任何问题。我在不同的布局中使用了它,它总是按预期工作。当然,我几年前就用过这个,我不确定它是否仍然有效。也许你可以试试另一种