我为分辨率为 480x800 的 Pantech 设备创建了我的应用程序,其高度和宽度以像素为单位。
我需要为 G1 设备转换高度和宽度。我认为将其转换为 dp 将解决问题并为两种设备提供相同的解决方案。
有什么简单的方法可以将像素转换为 dp?有什么建议么?
HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com
Java代码:
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
r.getDisplayMetrics()
);
科特林代码:
val dip = 14f
val r: Resources = resources
val px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
r.displayMetrics
)
Kotlin 扩展:
val Number.toPx get() = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this.toFloat(),
Resources.getSystem().displayMetrics)
huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式
注意:以上是将 DIP 转换为像素。最初的问题询问如何将像素转换为 Dips!
这是对 OP 的真实答案:stackoverflow.com/questions/6656540/…
有趣的是,当它没有真正回答问题时答案如何更有帮助-_-我以为我想要问题所问的,然后我意识到我没有!这么棒的答案。我确实有一个问题。如何获取 applyDimension 的最后一个参数?我可以只做getResource().getDisplayMetrics(),还是有别的?
注意:相对昂贵的操作。尝试缓存这些值以便更快地访问
如果无权访问 Context 对象,请使用 Resources.getSystem().getDisplayMetrics()
huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
/**
* This method converts device specific pixels to density independent pixels.
*
* @param px A value in px (pixels) unit. Which we need to convert into db
* @param context Context to get resources and device specific display metrics
* @return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context){
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
可能值得返回一个 int Math.round(px) 因为大多数方法都需要一个整数值
@MuhammadBabar 这是因为 160 dpi (mdpi) 是计算其他密度的基线密度。例如 hdpi 被认为是 mdpi 密度的 1.5 倍,这实际上只是 240 dpi 的另一种说法。有关所有密度,请参见下面的 Zsolt Safrany 的答案。
@TomTasche:来自 Resource.getSystem() 的文档(强调我的):“返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未针对当前屏幕进行配置(不能使用尺寸单位,不会因方向等而改变)。”
开发商可以选择上限/下限价值。最好将控制权交给开发人员。
我会推荐 DisplayMetrics.DENSITY_DEFAULT 而不是 160f developer.android.com/reference/android/util/…
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求
最好放入 Util.java 类
public static float dpFromPx(final Context context, final float px) {
return px / context.getResources().getDisplayMetrics().density;
}
public static float pxFromDp(final Context context, final float dp) {
return dp * context.getResources().getDisplayMetrics().density;
}
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求
这不适用于所有设备!这个答案的结果与使用 TypedValue.applyDimension 的结果在 OnePlus 3T 上是不一样的(可能是因为 OnePlus 在操作系统中内置了自定义缩放)。使用 TypedValue.applyDimension 会导致跨设备的行为一致。
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;
density 等于
.75 在 ldpi (120 dpi)
1.0 on mdpi(160 dpi;基线)
1.5 在 hdpi (240 dpi)
2.0 xhdpi (320 dpi)
3.0 在 xxhdpi (480 dpi)
4.0 在 xxxhdpi (640 dpi)
使用此 online converter 来处理 dpi 值。
编辑:dpi 存储桶和 density 之间似乎没有 1:1 的关系。看起来 Nexus 5X 是 xxhdpi 的 density 值为 2.625(而不是 3)。请在 Device Metrics 中亲自查看。
“看起来 Nexus 5X 是 xxhdpi 的密度值为 2.6(而不是 3)” - 从技术上讲,Nexus 5X 是 420dpi,而 Nexus 6/6P 是 560dpi,两者都没有直接落在标准存储桶之一中,就像带有 tvdpi (213dpi) 的 Nexus 7。因此,将这些列为 xxdpi 和 xxxhdpi 的网站是一场闹剧。您的图表是正确的,并且这些设备将根据其“特殊”dpi 存储桶正确缩放。
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
你可以使用这个 … 没有上下文
public static int pxToDp(int px) {
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
正如@Stan 提到的…如果系统改变密度,使用这种方法可能会导致问题。所以要注意这一点!
就我个人而言,我正在使用 Context 来做到这一点。这只是我想与您分享的另一种方法
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
您可能不想使用它。 getSystem() 的文档 - “返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未针对当前屏幕进行配置(不能使用维度单位,不会根据方向等进行更改) 。”
附和@Stan 所说的话:这是危险的,你不应该使用它,尤其是现在设备外形变得如此复杂。
这不考虑可折叠设备和 ChromeOS 设备
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
如果您可以使用尺寸 XML,那就很简单了!
在您的 res/values/dimens.xml 中:
120dp
...
...
然后在你的 Java 中:
getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
由于 px to dp 取决于屏幕密度,我不知道 OP 一开始是如何获得 120 的,除非他或她在所有不同的屏幕尺寸上测试了 px to dp 方法。
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求
根据Android开发指南:
px = dp * (dpi / 160)
但是,当您收到以像素为单位的设计时,您通常会希望以相反的方式执行此操作。所以:
dp = px / (dpi / 160)
如果您使用的是 240dpi 设备,则此比率为 1.5(如前所述),因此这意味着 60px 图标在应用程序中等于 40dp。
Indhu,您可以参考这里 developer.android.com/guide/practices/… 和 developer.android.com/reference/android/util/…
160不变,床答
user25 实际上答案很好。你没有在安卓屏幕上阅读过任何文档吗?在谈论 android 屏幕密度时,160 是一个普遍的常数。引用文档:“中等密度(mdpi)屏幕(~160dpi)。(这是基线密度)”。来吧,伙计
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
没有 Context,优雅的静态方法:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Resources.getSystem() javadoc 说“返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未针对当前屏幕进行配置(不能使用维度单位,不根据方向更改等)。 "这几乎说明你不应该这样做,即使它以某种方式有效。
我刚刚阅读了@AustynMahoney 的评论,并意识到这个答案并不像我最初想象的那么好,但是SO won't let me undo my upvote!啊!
huntsbot.com – 高效赚钱,自由工作
使用 kotlin-extension 让它变得更好
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()
更新:
由于 displayMetrics 是 global shared Resources 的一部分,我们可以使用 Resources.getSystem()
val Float.toPx get() = this * Resources.getSystem().displayMetrics.density
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density
val Int.toPx get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp get() = (this / Resources.getSystem().displayMetrics.density).toInt()
PS:根据@EpicPandaForce 的评论:
您不应该为此使用 Resources.getSystem(),因为它不处理可折叠设备和 Chrome OS 设备。
为什么要将它添加为 Int 的扩展,责任不必对 Int 类型做任何事情。
@htafoya 感谢您的反馈。我考虑你在上一版中的提及。
您不应为此使用 Resources.getSystem(),因为它不处理可折叠设备和 Chrome OS 设备。
HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com
对于DP to Pixel
在 dimens.xml 中创建一个值
20dp
在 pixel 中获取该值:
int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);
huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感
对于使用 Kotlin 的任何人:
val Int.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
用法:
64.toPx
32.toDp
来自 Resource.getSystem() 的文档:“返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未针对当前屏幕进行配置(不能使用维度单位,不会根据方向等)。”
@HendraWD 文档可能令人困惑,它提到的维度单位是您的应用程序级别的维度资源。 displayMetrics 不是应用程序级资源。它是一个系统资源,它返回正确的值。此代码在我所有的 Prod 应用程序上运行良好。从来没有问题。
我喜欢这个解决方案,但我最初将逻辑理解为倒退。我想输入 dp 值并说 myVal.dp。如果您认为我想要做的事情读起来更好,那么您将需要交换除法和乘法逻辑。另外我认为在这里使用 roundToInt() 而不是 toInt() 会更好一些。
@AdamJohns 因为所有与视图相关的函数都使用像素作为参数,所以我认为 64.toPx 会更有意义。我将其读取为 64 以转换为像素。但您可以随意更改顺序和名称。最后,重要的部分是是否将值乘以密度。
您不应该为此使用 Resources.getSystem() 。
原文链接:https://www.huntsbot.com/qa/QEYP/converting-pixels-to-dp?lang=zh_CN&from=csdn
huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式