我正在尝试计算可变数量的像素到密度独立像素,反之亦然。
此公式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
不适用于小型设备,因为它除以零。
这是我的dp to px公式:
px = (int)(dp * (displayMetrics.densityDpi / 160));
有人可以给我一些指示吗?
答案 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)
以下功能在我的设备上运行良好。
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()
,TypedValue
和TypedValue.complexToDimension()
调用TypedValue.complexToDimensionPixelOffset()
并转换由此获得的TypedValue.complexToDimensionPixelSize()
来实现所有这三项功能。
因此,如果要获取“原始”值以及XML源中指定的单位,请调用Resources.getValue()
并使用TypedValue
类的方法。
答案 19 :(得分:0)
随意使用我写的这个方法:
int dpToPx(int dp)
{
return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}