公式px到dp,dp到px android
我正试图计算可变数量的像素密度独立像素,反之亦然。
这个公式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
在小型设备上不起作用,因为它被零除。
这是我的DP到PX公式:
px = (int)(dp * (displayMetrics.densityDpi / 160));
有人能给我一些指点吗?
注意:上面广泛使用的解决scheme是基于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属性,你可能想区分,但我不能想象一个理智的显示,这些值差异很大。
我通过使用下面的公式解决了我的问题。 愿其他人从中受益。
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);
px到dp:
int valueInpx = ...; int valueInDp= (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources() .getDisplayMetrics());
只需调用getResources().getDimensionPixelSize(R.dimen.your_dimension)
将dp
单位转换为像素
使用此function
private int dp2px(int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); }
有效的方式
DP到像素:
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); }
希望这会帮助你。
px = dp * (dpi / 160) dp = px * (160 / dpi)
在大多数情况下,转换函数经常被调用。 我们可以通过添加记忆来优化它。 所以,它不会每次调用该函数。
我们来声明一个将存储计算值的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中的值并维护之前值的logging。
在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)); }
谢谢。
以下function在我的设备上运行良好。
它来自https://gist.github.com/laaptu/7867851
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); }
//获取十进制/浮点数
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)); }
如果您正在寻找一个在线计算器,以不同的屏幕密度将DP,SP,英寸,毫米,点或像素相互转换, 这是我所知道的最完整的工具 。
您可以使用[DisplayMatrics][1]
并确定屏幕密度。 像这样的东西:
int pixelsValue = 5; // margin in pixels float d = context.getResources().getDisplayMetrics().density; int margin = (int)(pixelsValue * d);
正如我记得最好使用地板偏移和四舍五入宽度。
随意使用这个方法我写道:
int dpToPx(int dp) { return (int) (dp * getResources().getDisplayMetrics().density + 0.5f); }
上面接受的答案不完全准确。 根据查看Android源代码获得的信息:
Resources.getDimension()
和getDimensionPixelOffset()
/ getDimensionPixelSize()
区别仅在于前者返回float
而后者则返回相同的值,并且适当地舍入为int
。 对于所有这些,返回值是在原始像素。
通过调用Resources.getValue()
,通过分别调用TypedValue.complexToDimension()
, TypedValue.complexToDimensionPixelOffset()
和TypedValue.complexToDimensionPixelSize()
转换获得的TypedValue
,从而实现所有这三个函数。
因此,如果您想要与XML源指定的单元一起获取“原始”值,请调用Resources.getValue()
并使用TypedValue
类的方法。
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); }
上面的ct_robsvariables的答案,如果你正在使用整数,不仅可以避免被0除,它也可以在小设备上产生一个可用的结果:
在整数计算中涉及最大精度乘除之前先除以减less截断效应。
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
在其他答案的帮助下,我写了这个函数。
public static int convertToPixels(Context context, int nDP) { final float conversionScale = context.getResources().getDisplayMetrics().density; return (int) ((nDP * conversionScale) + 0.5f) ; }