我正在尝试计算可变数量的像素到与密度无关的像素,反之亦然。
该公式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
不适用于小型设备,因为它被零除。
这是我的dp至px公式:
px = (int)(dp * (displayMetrics.densityDpi / 160));
有人可以给我一些指示吗?
我正在尝试计算可变数量的像素到与密度无关的像素,反之亦然。
该公式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
不适用于小型设备,因为它被零除。
这是我的dp至px公式:
px = (int)(dp * (displayMetrics.densityDpi / 160));
有人可以给我一些指示吗?
Answers:
注意:上面广泛使用的解决方案基于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());
typedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, valueInDp , getResources() .getDisplayMetrics());
从PX到DP,这也是最佳答案
applyDimension
仅产生像素。请参阅android.googlesource.com/platform/frameworks/base/+/refs/heads/…,其中未执行任何转换COMPLEX_UNIT_PX
。
dp
。如果您查看源代码TypedValue.COMPLEX_UNIT_DIP
,value * metrics.density
则会返回实际需要的位置value * metrics.density
。所以,你是什么getting` valueInDp`是不是在dp
为valueInPx
中px
。
value / metrics.density
”
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);
}
希望这会帮助你。
displayMetrics.xdpi
在任何设备上使用的都是不同的。令人遗憾的是,这个错误的答案最具有争议。
private fun dpToPx(dp: Int) = (dp * Resources.getSystem().displayMetrics.density).toInt()
只需调用getResources().getDimensionPixelSize(R.dimen.your_dimension)
即可将dp
单位转换为像素
使用此功能
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
在大多数情况下,转换函数经常被调用。我们可以通过添加备注来对其进行优化。因此,它不会每次调用函数时都进行计算。
让我们声明一个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;
}
一个备忘录功能,它从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));
}
谢谢。
下面的功能对我来说在各种设备上都很有效。
它取自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);
}
如果您正在寻找一种在线计算器,可以在不同的屏幕密度下相互转换DP,SP,英寸,毫米,点或像素,这是我所知道的最完整的工具。
//用于获取小数/浮点数
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));
}
上面接受的答案并不完全准确。根据通过检查Android源代码获得的信息:
Resources.getDimension()
和getDimensionPixelOffset()
/的getDimensionPixelSize()
不同之处仅在于前者返回float
,而后两者返回int
适当舍入后的相同值。对于所有这些,返回值以原始像素为单位。
所有三个功能是通过调用implementedy Resources.getValue()
和转换这样获得TypedValue
通过调用TypedValue.complexToDimension()
,TypedValue.complexToDimensionPixelOffset()
和TypedValue.complexToDimensionPixelSize()
分别。
因此,如果要与XML源中指定的单位一起获取“原始”值,请调用Resources.getValue()
并使用TypedValue
该类的方法。
上面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