将像素转换为dp


826

我创建的应用程序的分辨率是的Pantech设备的高度和宽度(以像素为单位)480x800

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

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


1
如果您要进行一次转换(例如,用于从Photoshop导出精灵),则可以使用一个漂亮的转换器
Paul Lammertsma


Answers:


1036
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    dip,
    r.getDisplayMetrics()
);

331
注意:以上将DIP转换为像素。最初的问题问如何将像素转换为Dips!
Eurig Jones

12
这里是一个真正的答案OP:stackoverflow.com/questions/6656540/...
的Qix

119
有趣的是,当答案没有真正回答问题时,答案会更有帮助-_-我以为我想问这个问题,然后才意识到自己没有!很好的答案。我有一个问题。如何获得最后的参数applyDimension?我可以做getResource().getDisplayMetrics(),还是还有别的吗?
安迪2012年

11
注意:相对昂贵的操作。尝试缓存值以加快访问速度
Entreco 2014年

8
如果无法使用Context对象Resources.getSystem().getDisplayMetrics()
Farshad Tahmasbi

871
/**
 * 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);
}

8
可能值得返回int Math.round(px),因为大多数方法都希望使用整数值
Raj Labana

3
@MuhammadBabar这是因为160 dpi(mdpi)是基线密度,可从中计算其他密度。例如,hdpi被认为是mdpi密度的1.5倍,这实际上只是说240 dpi的另一种方式。有关所有密度,请参见下面的Zsolt Safrany答案。
斯蒂芬

19
@TomTasche:从文档Resource.getSystem()(针对我的重点):“返回全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未配置为当前屏幕(无法使用尺寸单位,不会更改根据方向等)。”
Vicky Chijwani 2015年

2
开发人员可以选择隐藏/浮动值。最好将控制权交给开发人员。
Muhammad Nabeel Arif

7
我会推荐DisplayMetrics.DENSITY_DEFAULT而不是160f developer.android.com/reference/android/util/…–
milcaepsilon

285

最好放在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;
}

5
这不适用于所有设备!这个答案的结果与在OnePlus 3T上使用TypedValue.applyDimension的结果不同(可能是因为OnePlus在操作系统中内置了自定义缩放)。使用TypedValue.applyDimension会导致跨设备的一致行为。
本·德拉海耶

196
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;

density 等于

  • .75ldpi120dpi)
  • 1.0mdpi160dpi;基准)
  • 1.5hdpi240dpi)
  • 2.0xhdpi320dpi)
  • 3.0xxhdpi480dpi)
  • 4.0xxxhdpi640dpi)

使用此在线转换器可播放dpi值。

编辑:似乎dpi桶和之间没有1:1关系density。看起来该Nexus 5X存在物xxhdpidensity值为2.625(而不是3)。自己查看“ 设备指标”


3
“看起来Nexus 5X的xxhdpi的密度值为2.6(而不是3)”-从技术上讲,Nexus 5X是420dpi,而Nexus 6 / 6P是560dpi,两者都没有直接落在一个标准存储桶中,就像具有tvdpi(213dpi)的Nexus 7。因此,将这些列为xxdpi和xxxhdpi的站点是闹剧。您的图表是正确的,并且这些设备将根据其“特殊” dpi桶适当缩放。
史蒂芬·拜尔

107

您可以在没有上下文的情况下使用此..

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来做到这一点的。这是我想与您分享的另一种方法


11
您可能不想使用它。getSystem()的文档-“返回全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未配置为当前屏幕(无法使用尺寸单位,不会根据方向发生变化,等等) 。”
Stan

赞同@Stan的说法:这很危险,您不应该使用它,尤其是当设备尺寸变得如此复杂时。
萨凯特

93

如果可以使用维度XML,那将非常简单!

在您的res/values/dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="thumbnail_height">120dp</dimen>
    ...
    ...
</resources>

然后在您的Java中:

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

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

75

根据《 Android开发指南》:

px = dp * (dpi / 160)

但是,当您收到以像素表示的设计时,通常会希望以其他方式执行此操作。所以:

dp = px / (dpi / 160)

如果您使用的是240dpi的设备,则该比率为1.5(如前所述),因此这意味着60px图标在应用程序中等于40dp。



7
160是常数,床回答
user25

2
@ user25很好的答案。您没有在Android屏幕上阅读任何文档吗?160是讨论android屏幕密度时普遍使用的常量。来自文档的引言:“中等密度(mdpi)屏幕(〜160dpi)。(这是基准密度)”。来吧,伙计
mykolaj

70

没有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);
}

24
Resources.getSystem()javadoc说:“返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未针对当前屏幕进行配置(无法使用尺寸单位,不会根据方向发生变化,等等)。” 这几乎说,即使它以某种方式起作用,也不应该这样做。
Austyn Mahoney 2014年

我刚刚阅读了@AustynMahoney的评论,并意识到这个答案并不像我最初想象的那么好,但是我不会让我撤消我的支持!啊!
Vicky Chijwani 2015年

45

对于 DP to Pixel

在中创建一个值 dimens.xml

<dimen name="textSize">20dp</dimen>

将该值输入pixel为:

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

39

因此,您可以使用以下公式来根据dp中指定的尺寸计算正确的像素数量

public int convertToPx(int dp) {
    // Get the screen's density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (dp * scale + 0.5f);
}

4
这会将dp转换为像素,但是您调用了method convertToDp
Qwertie 2012年

4
+ 0.5f在这里解释-> developer.android.com/guide/practices/…。它用于四舍五入到最接近的整数。
2014年

唯一正确的答案。你可以添加源developer.android.com/guide/practices/...
user25


39

对于使用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

@HendraWD这些文档可能会令人困惑,它提到的尺寸单位是您的应用程序级别使资源变暗。displayMetrics不是应用程序级资源。它是系统资源,它返回正确的值。该代码在我所有的Prod应用程序上均能正常工作。从来没有问题。
Gunhan


27

使用kotlin扩展使它更好

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全局共享资源的一部分,我们可以使用Resources.getSystem()

fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()

fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()

4
为什么要将其添加为Int的扩展,而责任则不必对Int类型做任何事情。
htafoya

19

这应该使您将dp转换为像素:

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

这应该使您将像素转换为dp:

public static int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

19

科特林

fun convertDpToPixel(dp: Float, context: Context): Float {
    return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}

fun convertPixelsToDp(px: Float, context: Context): Float {
    return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}

爪哇

public static float convertDpToPixel(float dp, Context context) {
    return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

public static float convertPixelsToDp(float px, Context context) {
    return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

12

如果您在值/维度中包含维,则最好的方法可能是直接从getDimension()方法获取维,它将返回已转换为像素值的维。

context.getResources().getDimension(R.dimen.my_dimension)

为了更好地解释这一点,

getDimension(int resourceId) 

将返回已转换为像素的尺寸为A FLOAT。

getDimensionPixelSize(int resourceId)

将返回相同但被截断为int的值,因此为AS INTEGER。

请参阅Android参考


9
将dp转换为像素。
public static int dp2px(Resources resource, int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,   dp,resource.getDisplayMetrics());
}
将像素转换为dp。
  public static float px2dp(Resources resource, float px)  {
    return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}

资源是context.getResources()。


8
答案是错误的,因为您没有将像素转换为dp,而是将像素转换为像素!
Yaroslav

px2dp错误-将返回相同的像素值。
natario

8

像这样:

public class ScreenUtils {

    public static float dpToPx(Context context, float dp) {
        if (context == null) {
            return -1;
        }
        return dp * context.getResources().getDisplayMetrics().density;
    }

    public static float pxToDp(Context context, float px) {
        if (context == null) {
            return -1;
        }
        return px / context.getResources().getDisplayMetrics().density;
    }
}

取决于上下文,返回浮点值,静态方法

来自:https : //github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ScreenUtils.java#L15


8

使用Kotlin扩展功能的更优雅方法

/**
 * Converts dp to pixel
 */
val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()

/**
 * Converts pixel to dp
 */
val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()

用法:

println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")

喜欢在这里使用扩展名。我将函数读为“转换为function name”,在这种情况下我意识到这是倒退的。为了阐明每个函数的意图,可以将函数的名称更新为分别读取dpToPx和pxToDp。
麦克斯韦

从Resource.getSystem()的文档中:“返回全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问,并且未配置为当前屏幕(不能使用尺寸单位,不会基于方向等)。”
HendraWD

7
float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);

2
这不仅与该问题的许多其他答案所涵盖的内容相同吗?
TZHX

7

如果您开发的是性能至关重要的应用程序,请考虑以下优化的类:

public final class DimensionUtils {

    private static boolean isInitialised = false;
    private static float pixelsPerOneDp;

    // Suppress default constructor for noninstantiability.
    private DimensionUtils() {
        throw new AssertionError();
    }

    private static void initialise(View view) {
        pixelsPerOneDp = view.getResources().getDisplayMetrics().densityDpi / 160f;
        isInitialised = true;
    }

    public static float pxToDp(View view, float px) {
        if (!isInitialised) {
            initialise(view);
        }

        return px / pixelsPerOneDp;
    }

    public static float dpToPx(View view, float dp) {
        if (!isInitialised) {
            initialise(view);
        }

        return dp * pixelsPerOneDp;
    }
}

仅当您真正频繁地进行转换时,它才有意义。就我而言。
帕维尔

什么是160f?为什么使用它,为什么它是160?
dephinera 2015年

160 => 160dpi,这是因为公式而导致转换度量
xAqweRx

6

要将Pixels转换为dp,请使用TypedValue

如文档所述:动态类型数据值的容器。

并使用applyDimension方法:

public static float applyDimension (int unit, float value, DisplayMetrics metrics) 

它将保存维的解压缩复杂数据值转换为其最终浮点值,如下所示:

Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());

希望对您有所帮助。


6

这对我来说是这样的:

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int  h = displaymetrics.heightPixels;
float  d = displaymetrics.density;
int heightInPixels=(int) (h/d);

您可以对宽度进行相同的操作。



4

您应该像使用像素一样使用dp。这就是全部。显示独立的像素。使用与在中密度屏幕上相同的数字,并且在高密度屏幕上尺寸会神奇地正确。

但是,听起来您需要的是布局设计中的fill_parent选项。当您希望视图或控件扩展到父容器中所有剩余的大小时,请使用fill_parent。


其实我的问题是我的应用程序编码的高密度显示屏,现在需要将其转换为低密度屏幕..
Indhu

修改中等密度屏幕的像素(您可以在模拟器中设置中等密度屏幕),然后将像素替换为dp。但是,可以使用fill_parent和多个布局制作更灵活的应用程序。
Michael Lowman

最后,我别无选择,只能手动将所有px更改为dp。
::

1
至少下次您将首先使用dp,而不必进行任何更改:)尽管应该可以使用在大多数情况下不需要绝对定位的布局。
Michael Lowman

因为这是我的第一个应用程序,所以我犯了这个错误。。。我再也做不到... :)
Indhu 2011年

4

PXDP不同但相似。

DP是仅考虑屏幕物理尺寸时的分辨率。当您使用DP它时,会将您的布局缩放到具有不同pixel密度的其他类似尺寸的屏幕。

有时您确实需要,pixels但是在代码中处理尺寸时pixels,除非您进行转换,否则始终会处理real 。

因此,在Android设备上,正常大小的hdpi屏幕800x480 is 533x320处于DP(我相信)。转换DPpixels /1.5,转换回*1.5。这仅适用于一个屏幕大小dpi,并且会根据设计而变化。pixels虽然我们的艺术家给了我,但我DP用上述1.5等式转化为我。


3

如果需要Integer值,则使用Math.round()会将float舍入到最接近的整数。

public static int pxFromDp(final float dp) {
        return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
    }

2

这对我有用(C#):

int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);

不是这个问题的答案,但是对于C#来说,它可以工作。谢谢
Yekmer Simsek

2

科特林

   fun spToPx(ctx: Context, sp: Float): Float {
    return sp * ctx.resources.displayMetrics.scaledDensity
}

fun pxToDp(context: Context, px: Float): Float {
    return px / context.resources.displayMetrics.density
}

fun dpToPx(context: Context, dp: Float): Float {
    return dp * context.resources.displayMetrics.density
}

爪哇

   public static float spToPx(Context ctx,float sp){
    return sp * ctx.getResources().getDisplayMetrics().scaledDensity;
}

public static float pxToDp(final Context context, final float px) {
    return px / context.getResources().getDisplayMetrics().density;
}

public static float dpToPx(final Context context, final float dp) {
    return dp * context.getResources().getDisplayMetrics().density;
}

2

最好的答案来自Android框架本身:只需使用这种相等性即可...

public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
    final float scale = display_metrics.density;
    return (int) (dps * scale + 0.5f);
}

(将dp转换为px)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.