Converting pixels to dp

792,415

Solution 1

Java code:

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

Kotlin code:

 val dip = 14f
 val r: Resources = resources
 val px = TypedValue.applyDimension(
     TypedValue.COMPLEX_UNIT_DIP,
     dip,
     r.displayMetrics
 )

Kotlin extension:

val Number.toPx get() = TypedValue.applyDimension(
  TypedValue.COMPLEX_UNIT_DIP,
  this.toFloat(),
  Resources.getSystem().displayMetrics)

Solution 2

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

Solution 3

Preferably put in a Util.java class

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;
}

Solution 4

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

density equals

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

Use this online converter to play around with dpi values.

EDIT: It seems there is no 1:1 relationship between dpi bucket and density. It looks like the Nexus 5X being xxhdpi has a density value of 2.625 (instead of 3). See for yourself in the Device Metrics.

Solution 5

You can use this .. without Context

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

As @Stan mentioned .. using this approach may cause issue if system changes density. So be aware of that!

Personally I am using Context to do that. It's just another approach I wanted to share you with

Share:
792,415
Indhu
Author by

Indhu

Updated on July 08, 2022

Comments

  • Indhu
    Indhu almost 2 years

    I have created my application with the height and width given in pixels for a Pantech device whose resolution is 480x800.

    I need to convert height and width for a G1 device.
    I thought converting it into dp will solve the problem and provide the same solution for both devices.

    Is there any easy way to convert pixels to dp?
    Any suggestions?

  • Indhu
    Indhu over 13 years
    actually my problem is my application is coded for high density screen and now it needs to be converted to low density screen..
  • Michael Lowman
    Michael Lowman over 13 years
    modify your pixels for a medium density screen (you can set up a medium density screen in the emulator) and replace the pixel with dp. However, more flexible applications can be made using fill_parent and multiple layouts.
  • Indhu
    Indhu over 13 years
    Finally, i had no option but to change all the px to dp manually.. :(
  • Michael Lowman
    Michael Lowman over 13 years
    At least next time you'll use dp first and won't have to change anything :) Although it should be possible to use layouts that don't require absolute positioning for most things.
  • Indhu
    Indhu over 13 years
    Since it was my first app.. i made this mistake... i ll never do it again...:)
  • Eurig Jones
    Eurig Jones about 12 years
    Note: The above is converting DIPs to Pixels. The original question asked how to convert pixels to Dips!
  • qix
    qix about 12 years
    Here's a real answer to the OP: stackoverflow.com/questions/6656540/…
  • Qwertie
    Qwertie almost 12 years
    This converts dp to pixels but you called your method convertToDp.
  • Sachchidanand
    Sachchidanand almost 12 years
  • Andy
    Andy almost 12 years
    Its funny how the answer is more helpful when it doesn't really answer the question -_- I thought I wanted what the question asked then I realized I didn't! So great answer. I do have a question. How can I obtain the last paramter for applyDimension? Can I just do getResource().getDisplayMetrics(), or is there something else?
  • Austyn Mahoney
    Austyn Mahoney over 10 years
    Resources.getSystem() javadoc says "Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc)." This pretty much says you shouldn't be doing this even if it somehow works.
  • Josh
    Josh about 10 years
    You should be using this one. As a bonus it will also do SP.
  • Pavel
    Pavel about 10 years
    It makes sence only if you do convertations really frequently. In my case I do.
  • Bae
    Bae almost 10 years
    +0.5f is explain here --> developer.android.com/guide/practices/… . It's used to round up to the nearest integer.
  • Entreco
    Entreco over 9 years
    NOTE: relatively expensive operation. Try to cache the values for quicker acces
  • vovahost
    vovahost over 9 years
    resultPix should be of type int. int resultPix = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getR‌​esources().getDispla‌​yMetrics())
  • TZHX
    TZHX about 9 years
    Is this not just the same as what's covered in many of the other answers to this question?
  • Raj
    Raj almost 9 years
    Might be worth returning an int Math.round(px) as most methods expect an integer value
  • Stephen
    Stephen almost 9 years
    @MuhammadBabar This is because 160 dpi (mdpi) is the baseline desity from which other densities are calculated. hdpi for instance is considered to be 1.5x the density of mdpi which is really just another way of saying 240 dpi. See Zsolt Safrany's answer below for all densities.
  • Vicky Chijwani
    Vicky Chijwani almost 9 years
    @TomTasche: From the docs for Resource.getSystem() (emphasis mine): "Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc)."
  • Vicky Chijwani
    Vicky Chijwani almost 9 years
    I just read @AustynMahoney's comment and realized this answer isn't as great as I originally thought, but SO won't let me undo my upvote! Argh!
  • Martin Pfeffer
    Martin Pfeffer over 8 years
    pixel returns float? I don't think there is "a half of a pixel"... :)
  • Muhammad Nabeel Arif
    Muhammad Nabeel Arif over 8 years
    Developer have a choice to ceil/floor the value. It is better to give control to developer.
  • dephinera
    dephinera over 8 years
    What is 160f? Why do you use it, why is it 160?
  • box
    box over 8 years
    This is not the right way to make conversion from px to dp. Check @Mike Keskinov's answer.
  • DemonGyro
    DemonGyro over 8 years
    I haven't tried it, but it's logically possible to convert from pixels to DP by using this code by doing the following: float pixelsPerDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, r.getDisplayMetrics()); return dp / pixelsPerDp;
  • milcaepsilon
    milcaepsilon over 8 years
    I would recommand DisplayMetrics.DENSITY_DEFAULT instead of 160f developer.android.com/reference/android/util/…
  • xAqweRx
    xAqweRx over 8 years
    160 => 160dpi and this is for converting measures because of formula
  • Gokhan Arik
    Gokhan Arik about 8 years
    This won't give the correct result. (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT) will return an int. It needs to be cast to double or float.
  • Livven
    Livven about 8 years
    @VickyChijwani Resources.getSystem().getDisplayMetrics().densityDpi still seems to work.
  • Livven
    Livven about 8 years
    Instead of (float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT you could also just use metrics.density.
  • Vicky Chijwani
    Vicky Chijwani about 8 years
    @Livven I know it works, but that's beside the point, which was that the implementation can change / stop working at any time because the documentation doesn't match what we expect.
  • Livven
    Livven about 8 years
    @VickyChijwani Fair enough. I often find that when the documentation doesn't match the behavior it's because the documentation is outdated or simply not properly maintained, rather than the actual behavior being unintended. With some, maybe even most frameworks, relying only on the documentation would pretty much prevent you from getting any work done or even cause bugs.
  • Yaroslav
    Yaroslav almost 8 years
    The answer is wrong, because you are not converting pixels to dp - you are converting pixels to pixels!
  • user25
    user25 over 7 years
    160 is constant, bed answer
  • user25
    user25 over 7 years
    the only right answer. you could add the source developer.android.com/guide/practices/…
  • user25
    user25 over 7 years
    what is that??? I convert 3dp to px using it and I get 1564.5px??. it's better to use developer.android.com/guide/practices/…
  • Steven Byle
    Steven Byle over 7 years
    "It looks like the Nexus 5X being xxhdpi has a density value of 2.6 (instead of 3)" - Technically the Nexus 5X is 420dpi and the Nexus 6/6P is 560dpi, neither land directly in one of the standard buckets, just like the Nexus 7 with tvdpi (213dpi). So the site listing those as xxdpi and xxxhdpi is a farce. Your chart IS correct, and those devices will properly scale based one their "special" dpi buckets.
  • Gatunox
    Gatunox over 7 years
    HAHAHAAHAA. Pixels as a FLOAT , that's good... I am wondering, How can you paint 1,5 pixels, LOL
  • Yekmer Simsek
    Yekmer Simsek over 7 years
    Not an answer to this question but for C# it works. Thanks
  • Aksiom
    Aksiom over 7 years
    Please don't use this if you want to load a dp value from your dimens.xml, because the getResource().getDimension() already does that for you. If you want to directly round the base value and cast it to an int then use the getDimensionPixelSize() instead of getDimension().
  • Stan
    Stan over 7 years
    You might not want to use this. Documentation for getSystem() - "Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc)."
  • Lorne Laliberte
    Lorne Laliberte about 7 years
    @Gatuox You can in fact paint fractions of pixels. Look up antialiasing techniques. You draw adjacent pixels at varying levels of alpha to approximate the fractions.
  • Farshad Tahmasbi
    Farshad Tahmasbi almost 7 years
    If have no access to Context object use Resources.getSystem().getDisplayMetrics()
  • John61590
    John61590 almost 7 years
    Since px to dp depends on screen density, I don't know how the OP got 120 in the first place, unless he or she tested the px to dp method on all different screen sizes.
  • Maxwell
    Maxwell almost 7 years
    Love the use of extension here. I read the functions as "convert to function name" which I realize is backwards in this case. To clarify each function's intent, the names of the functions could be updated to read dpToPx and pxToDp, respectively.
  • mykolaj
    mykolaj almost 6 years
    @user25 Great answer actually. Haven't you read any docs on android screens? 160 is a common constant all over the place when talking about android screen densities. Quote from docs: "medium-density (mdpi) screens (~160dpi). (This is the baseline density)". Come on, man
  • Ben De La Haye
    Ben De La Haye almost 6 years
    This does not work on all devices! The result of this answer vs that of using TypedValue.applyDimension is not the same on a OnePlus 3T (probably because OnePlus have custom scaling built into the OS). Using TypedValue.applyDimension causes consistent behavior across devices.
  • Pants
    Pants over 5 years
    With App Widgets I get two different results when using context.getResources().getDisplayMetrics() and Resources.getSystem().getDisplayMetrics()
  • HendraWD
    HendraWD over 5 years
    From the docs for Resource.getSystem(): "Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc)."
  • HendraWD
    HendraWD over 5 years
    From the docs for Resource.getSystem(): "Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc)."
  • Gunhan
    Gunhan over 5 years
    @HendraWD The docs may be confusing, the dimension units it is mentioning is your application level dimens resources. displayMetrics is not an application level resource. It is a system resource and it returns the correct values. This code is working fine on all of my Prod apps. Never had an issue.
  • natario
    natario over 5 years
    The px2dp is wrong - will return the same value in pixels.
  • caw
    caw almost 5 years
    web.archive.org/web/20140808234241/http://developer.android.‌​com/… for a link that still has the content in question
  • Saket
    Saket almost 5 years
    Seconding what @Stan is saying: this is dangerous and you shouldn't be using it, especially now when device form factors are becoming so complex.
  • htafoya
    htafoya over 4 years
    Why would you add it as an extension of Int, the responsibility doesn't have to do anything with the Int type.
  • Juan Mendez
    Juan Mendez over 4 years
    kotlin: fun Context.convertDpToPixel(dp: Float): Float { return dp * (resources.displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT) } fun Context.convertPixelToDp(px:Float): Float { return px / (resources.displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT) }
  • EpicPandaForce
    EpicPandaForce about 3 years
    This is not considering foldables and ChromeOS devices
  • beigirad
    beigirad about 3 years
    @htafoya thanks for your feedback. I consider your mention in the last edition.
  • Adam Johns
    Adam Johns about 3 years
    I like this solution, but I initially read the logic as backwards. I was wanting to type the dp value and say myVal.dp. If you think what I was wanting to do reads nicer, then you'll want to swap the divide and multiply logic. Also I think it is slightly better to use roundToInt() instead of toInt() here.
  • Gunhan
    Gunhan about 3 years
    @AdamJohns Because all the View related functions use Pixels as arguments, I though 64.toPx would make more sense. I read it as 64 to -be converted- to pixels. But feel free to change the order and names as you wish. At the end the important part is if you multiply the value by density or not.
  • ericn
    ericn almost 3 years
    1) Why do you need ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT) when there is already context.getResources().getDisplayMetrics().density? 2) Why is pixels in Float type instead of int/ Integer?
  • Aman
    Aman over 2 years
    As @Andy said, most of searched how to convert pixel to dp, but the one we need often is to convert dp to pixel
  • Rickertbrandsen
    Rickertbrandsen over 2 years
    I think your post needs some extra words and a little bit of formatting, at one point i thought i am on completely different question.
  • EpicPandaForce
    EpicPandaForce about 2 years
    You should not be using Resources.getSystem() for this, because it does not handle foldables and Chrome OS devices.
  • EpicPandaForce
    EpicPandaForce about 2 years
    You should not be using Resources.getSystem() for this.
  • EpicPandaForce
    EpicPandaForce about 2 years
    You should not be using Resources.getSystem() for this.
  • EpicPandaForce
    EpicPandaForce about 2 years
    You should not be using Resources.getSystem() for this.