将像素转换为dp

Ind*_*dhu 789 android resolution pixel dpi

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

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

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

小智 1001

// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    dip,
    r.getDisplayMetrics()
);
Run Code Online (Sandbox Code Playgroud)

  • 注意:以上是将DIP转换为像素.原始问题询问如何将像素转换为Dips! (316认同)
  • 有趣的是,当答案没有真正回答问题时,答案会更有帮助-_-我以为我想问的问题然后我意识到我没有!那么好的答案.我有一个问题.我怎样才能获得`applyDimension`的最后一个参数?我可以只做`getResource().getDisplayMetrics()`,还是还有别的什么? (113认同)
  • 以下是OP的真实答案:http://stackoverflow.com/questions/6656540/android-convert-px-to-dp-video-aspect-ratio (12认同)
  • 注意:操作比较昂贵.尝试缓存值以便更快地访问 (10认同)
  • 如果无法访问`Context`对象,请使用`Resources.getSystem().getDisplayMetrics()` (5认同)

Muh*_*rif 843

/**
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

  • @TomTasche:来自[`Resource.getSystem()`]的文档(http://developer.android.com/reference/android/content/res/Resources.html#getSystem%28%29)(强调我的): "返回一个全局共享资源对象,该对象仅提供对系统资源的访问权限(无应用程序资源),并且未针对当前屏幕进行配置(**不能使用维度单位**,不会根据方向更改等)." (19认同)
  • 我建议使用`DisplayMetrics.DENSITY_DEFAULT`而不是`160f` http://developer.android.com/reference/android/util/DisplayMetrics.html#DENSITY_DEFAULT (7认同)
  • 可能值得返回一个int Math.round(px),因为大多数方法都期望一个整数值 (5认同)
  • @MuhammadBabar这是因为160 dpi(mdpi)是计算其他密度的基线desity.例如,hdpi被认为是mdpi密度的1.5倍,这实际上只是说240 dpi的另一种方式.有关所有密度,请参阅下面的Zsolt Safrany的答案. (3认同)
  • 开发人员可以选择限制/降低价值。最好将控制权交给开发人员。 (2认同)

Mik*_*nov 275

最好放在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;
}
Run Code Online (Sandbox Code Playgroud)

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

Zso*_*any 192

float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;
Run Code Online (Sandbox Code Playgroud)

density 等于

  • .75on ldpi(120dpi)
  • 1.0on mdpi(160dpi; baseline)
  • 1.5on hdpi(240dpi)
  • 2.0on xhdpi(320dpi)
  • 3.0on xxhdpi(480dpi)
  • 4.0on xxxhdpi(640dpi)

使用此在线转换器来播放dpi值.

编辑:似乎dpi桶和之间没有1:1的关系density.它看起来像Nexus 5X存在xxhdpi具有density的价值2.625(而不是3).请参阅设备指标中的自己.

  • "看起来像xxhdpi的Nexus 5X的密度值为2.6(而不是3)" - 技术上,Nexus 5X是420dpi,而Nexus 6/6P是560dpi,它们都没有直接落在其中一个标准桶中,就像Nexus 7带有tvdpi(213dpi).因此,列出xxdpi和xxxhdpi的网站是一场闹剧.您的图表是正确的,并且这些设备将根据其"特殊"dpi存储桶正确扩展. (3认同)

Ale*_*lex 91

如果你可以使用尺寸XML,那就非常简单了!

在你的res/values/dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="thumbnail_height">120dp</dimen>
    ...
    ...
</resources>
Run Code Online (Sandbox Code Playgroud)

然后在你的Java中:

getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
Run Code Online (Sandbox Code Playgroud)


Mah*_*raa 90

您可以使用此.. 没有上下文

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);
}
Run Code Online (Sandbox Code Playgroud)

正如@Stan所提到的......如果系统改变密度,使用这种方法可能会引起问题.所以要注意这一点!

就个人而言,我正在使用Context来做到这一点.

  • 您可能不想使用它.getSystem()的文档 - "返回一个全局共享的Resources对象,它只提供对系统资源的访问(没有应用程序资源),并且没有为当前屏幕配置(不能使用维度单位,不会根据方向更改等) ". (11认同)

Ric*_*ães 74

根据Android开发指南:

px = dp * (dpi / 160)
Run Code Online (Sandbox Code Playgroud)

但是,当您收到以像素为单位的设计时,通常您会希望以相反的方式执行此操作.所以:

dp = px / (dpi / 160)
Run Code Online (Sandbox Code Playgroud)

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

  • 160是不变的,床上的答案 (7认同)
  • Indhu,你可以在这里参考http://developer.android.com/guide/practices/screens_support.html#dips-pels和http://developer.android.com/reference/android/util/DisplayMetrics.html#density (2认同)
  • @ user25很好的答案。您没有在Android屏幕上阅读任何文档吗?160是讨论android屏幕密度时普遍使用的常量。来自文档的引用:“中等密度(mdpi)屏幕(〜160dpi)。(这是基准密度)”。来吧,伙计 (2认同)

Ada*_*zyk 69

没有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);
}
Run Code Online (Sandbox Code Playgroud)

  • `Resources.getSystem()`javadoc说"返回一个全局共享的Resources对象,它只提供对系统资源的访问(没有应用程序资源),并且没有为当前屏幕配置(不能使用维度单位,不会根据方向改变)等)." 这几乎说你不应该这样做,即使它以某种方式工作. (24认同)

小智 41

对于 DP to Pixel

在中创建一个值 dimens.xml

<dimen name="textSize">20dp</dimen>
Run Code Online (Sandbox Code Playgroud)

获取该值为pixel:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);
Run Code Online (Sandbox Code Playgroud)


nee*_*j t 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么+ 0.5f? (5认同)
  • 这会将dp转换为像素,但您调用了方法`convertToDp`. (4认同)
  • + 0.5f在这里解释 - > http://developer.android.com/guide/practices/screens_support.html#dips-pels.它用于向上舍入到最接近的整数. (4认同)

Gun*_*han 36

对于使用Kotlin的任何人:

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

val Int.toDp: Int
    get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Run Code Online (Sandbox Code Playgroud)

用法:

64.toPx
32.toDp
Run Code Online (Sandbox Code Playgroud)


Kva*_*ant 33

android SDK中有一个默认的util:http: //developer.android.com/reference/android/util/TypedValue.html

float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
Run Code Online (Sandbox Code Playgroud)

  • `resultPix`应该是int类型.`int resultPix =(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())` (2认同)

bei*_*rad 22

使用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()
Run Code Online (Sandbox Code Playgroud)

更新:

由于displayMetrics全局共享资源的一部分,我们可以使用Resources.getSystem()

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

fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
Run Code Online (Sandbox Code Playgroud)

  • 为什么要将它添加为 Int 的扩展,责任不必对 Int 类型做任何事情。 (13认同)

Ven*_*WAR 19

这应该给你转换dp到像素:

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Run Code Online (Sandbox Code Playgroud)

这应该给你转换像素到dp:

public static int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Run Code Online (Sandbox Code Playgroud)


Khe*_*raj 18

科特林

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)
}
Run Code Online (Sandbox Code Playgroud)

Java的

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);
}
Run Code Online (Sandbox Code Playgroud)


Lor*_*gli 12

可能最好的方法是,如果你有维度在值/维度内是直接从getDimension()方法获取维度,它将返回已经转换为像素值的维度.

context.getResources().getDimension(R.dimen.my_dimension)
Run Code Online (Sandbox Code Playgroud)

为了更好地解释这一点,

getDimension(int resourceId) 
Run Code Online (Sandbox Code Playgroud)

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

getDimensionPixelSize(int resourceId)
Run Code Online (Sandbox Code Playgroud)

将返回相同但截断为int,因此AS AN INTEGER.

请参阅Android参考


you*_*nes 10

科特林:

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
}
Run Code Online (Sandbox Code Playgroud)

爪哇:

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;
}
Run Code Online (Sandbox Code Playgroud)


Pri*_*pta 9

将dp转换为像素.

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

其中资源是context.getResources().

  • 答案是错误的,因为您没有将像素转换为dp - 您将像素转换为像素! (8认同)

Tri*_*nea 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

依赖于Context,返回浮点值,静态方法

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


Sae*_*umi 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()
Run Code Online (Sandbox Code Playgroud)

用法:

println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")
Run Code Online (Sandbox Code Playgroud)


Pav*_*vel 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;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

这是它对我有用的方式:

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int  h = displaymetrics.heightPixels;
float  d = displaymetrics.density;
int heightInPixels=(int) (h/d);
Run Code Online (Sandbox Code Playgroud)

您可以对宽度执行相同的操作.


小智 6

要将像素转换为dp,请使用TypedValue.

正如文档中提到的:用于动态类型化数据值的容器.

并使用applyDimension方法:

public static float applyDimension (int unit, float value, DisplayMetrics metrics) 
Run Code Online (Sandbox Code Playgroud)

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

Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());
Run Code Online (Sandbox Code Playgroud)

希望有助于.


Sib*_*bin 6

float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);
Run Code Online (Sandbox Code Playgroud)

  • 这不仅仅与这个问题的许多其他答案中涵盖的内容相同吗? (2认同)

Mic*_*man 5

您应该像使用像素一样使用dp.这就是他们的全部; 显示独立像素.使用与中密度屏幕相同的数字,并且在高密度屏幕上的大小将神奇地正确.

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


Kai*_*ang 5

上面有很多很棒的解决方案。但是,我发现最好的解决方案是google的设计:

https://design.google.com/devices/

密度