将像素转换为 dp

问:

我为分辨率为 480x800 的 Pantech 设备创建了我的应用程序,其高度和宽度以像素为单位。

我需要为 G1 设备转换高度和宽度。我认为将其转换为 dp 将解决问题并为两种设备提供相同的解决方案。

有什么简单的方法可以将像素转换为 dp?有什么建议么?

答1:

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

答2:

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/…

答3:

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 会导致跨设备的行为一致。

答4:

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 存储桶正确缩放。

答5:

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 设备

答6:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

如果您可以使用尺寸 XML,那就很简单了!

在您的 res/values/dimens.xml 中:



    120dp
    ...
    ...


然后在你的 Java 中:

getResources().getDimensionPixelSize(R.dimen.thumbnail_height);

由于 px to dp 取决于屏幕密度,我不知道 OP 一开始是如何获得 120 的,除非他或她在所有不同的屏幕尺寸上测试了 px to dp 方法。

答7:

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)。(这是基线密度)”。来吧,伙计

答8:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–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!啊!

答9:

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 设备。

答10:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

对于DP to Pixel

在 dimens.xml 中创建一个值

20dp

在 pixel 中获取该值:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);

答11:

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大洲远程工作机会,探索不一样的工作方式

猜你喜欢

转载自blog.csdn.net/kalman2019/article/details/128732239
DP