Converting pixels to dp
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
onldpi
(120
dpi) -
1.0
onmdpi
(160
dpi; baseline) -
1.5
onhdpi
(240
dpi) -
2.0
onxhdpi
(320
dpi) -
3.0
onxxhdpi
(480
dpi) -
4.0
onxxxhdpi
(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
Indhu
Updated on July 08, 2022Comments
-
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 over 13 yearsactually my problem is my application is coded for high density screen and now it needs to be converted to low density screen..
-
Michael Lowman over 13 yearsmodify 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 over 13 yearsFinally, i had no option but to change all the px to dp manually.. :(
-
Michael Lowman over 13 yearsAt 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 over 13 yearsSince it was my first app.. i made this mistake... i ll never do it again...:)
-
Eurig Jones about 12 yearsNote: The above is converting DIPs to Pixels. The original question asked how to convert pixels to Dips!
-
qix about 12 yearsHere's a real answer to the OP: stackoverflow.com/questions/6656540/…
-
Qwertie almost 12 yearsThis converts dp to pixels but you called your method
convertToDp
. -
Sachchidanand almost 12 yearsIndhu, You can refer here developer.android.com/guide/practices/… and developer.android.com/reference/android/util/…
-
Andy almost 12 yearsIts 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 dogetResource().getDisplayMetrics()
, or is there something else? -
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 about 10 yearsYou should be using this one. As a bonus it will also do SP.
-
Pavel about 10 yearsIt makes sence only if you do convertations really frequently. In my case I do.
-
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 over 9 yearsNOTE: relatively expensive operation. Try to cache the values for quicker acces
-
vovahost over 9 years
resultPix
should be of type int.int resultPix = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
-
TZHX about 9 yearsIs this not just the same as what's covered in many of the other answers to this question?
-
Raj almost 9 yearsMight be worth returning an int Math.round(px) as most methods expect an integer value
-
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 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 almost 9 yearsI 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 over 8 yearspixel returns float? I don't think there is "a half of a pixel"... :)
-
Muhammad Nabeel Arif over 8 yearsDeveloper have a choice to ceil/floor the value. It is better to give control to developer.
-
dephinera over 8 yearsWhat is 160f? Why do you use it, why is it 160?
-
box over 8 yearsThis is not the right way to make conversion from px to dp. Check @Mike Keskinov's answer.
-
DemonGyro over 8 yearsI 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 over 8 yearsI would recommand
DisplayMetrics.DENSITY_DEFAULT
instead of160f
developer.android.com/reference/android/util/… -
xAqweRx over 8 years160 => 160dpi and this is for converting measures because of formula
-
Gokhan Arik about 8 yearsThis won't give the correct result.
(metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)
will return anint
. It needs to be cast to double or float. -
Livven about 8 years@VickyChijwani
Resources.getSystem().getDisplayMetrics().densityDpi
still seems to work. -
Livven about 8 yearsInstead of
(float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT
you could also just usemetrics.density
. -
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 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 almost 8 yearsThe answer is wrong, because you are not converting pixels to dp - you are converting pixels to pixels!
-
user25 over 7 years160 is constant, bed answer
-
user25 over 7 yearsthe only right answer. you could add the source developer.android.com/guide/practices/…
-
user25 over 7 yearswhat 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 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 over 7 yearsHAHAHAAHAA. Pixels as a FLOAT , that's good... I am wondering, How can you paint 1,5 pixels, LOL
-
Yekmer Simsek over 7 yearsNot an answer to this question but for C# it works. Thanks
-
Aksiom over 7 yearsPlease 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 over 7 yearsYou 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 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 almost 7 yearsIf have no access to
Context
object useResources.getSystem().getDisplayMetrics()
-
John61590 almost 7 yearsSince 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 almost 7 yearsLove 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 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 almost 6 yearsThis 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 over 5 yearsWith App Widgets I get two different results when using
context.getResources().getDisplayMetrics()
andResources.getSystem().getDisplayMetrics()
-
HendraWD over 5 yearsFrom 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 over 5 yearsFrom 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 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 over 5 yearsThe px2dp is wrong - will return the same value in pixels.
-
caw almost 5 yearsweb.archive.org/web/20140808234241/http://developer.android.com/… for a link that still has the content in question
-
Saket almost 5 yearsSeconding 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 over 4 yearsWhy would you add it as an extension of Int, the responsibility doesn't have to do anything with the Int type.
-
Juan Mendez over 4 yearskotlin: 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 about 3 yearsThis is not considering foldables and ChromeOS devices
-
beigirad about 3 years@htafoya thanks for your feedback. I consider your mention in the last edition.
-
Adam Johns about 3 yearsI 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 useroundToInt()
instead oftoInt()
here. -
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 almost 3 years1) Why do you need
((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT)
when there is alreadycontext.getResources().getDisplayMetrics().density
? 2) Why is pixels in Float type instead of int/ Integer? -
Aman over 2 yearsAs @Andy said, most of searched how to convert pixel to dp, but the one we need often is to convert dp to pixel
-
Rickertbrandsen over 2 yearsI 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 about 2 yearsYou should not be using
Resources.getSystem()
for this, because it does not handle foldables and Chrome OS devices. -
EpicPandaForce about 2 yearsYou should not be using Resources.getSystem() for this.
-
EpicPandaForce about 2 yearsYou should not be using Resources.getSystem() for this.
-
EpicPandaForce about 2 yearsYou should not be using Resources.getSystem() for this.