Formula px to dp, dp to px android
Solution 1
Note: The widely used solution above is based on displayMetrics.density
. However, the docs explain that this value is a rounded value, used with the screen 'buckets'. Eg. on my Nexus 10 it returns 2, where the real value would be 298dpi (real) / 160dpi (default) = 1.8625.
Depending on your requirements, you might need the exact transformation, which can be achieved like this:
[Edit] This is not meant to be mixed with Android's internal dp unit, as this is of course still based on the screen buckets. Use this where you want a unit that should render the same real size on different devices.
Convert dp to pixel:
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
Convert pixel to dp:
public int pxToDp(int px) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
Note that there are xdpi and ydpi properties, you might want to distinguish, but I can't imagine a sane display where these values differ greatly.
Solution 2
I solved my problem by using the following formulas. May other people benefit from it.
dp to px:
displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);
px to dp:
displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);
Solution 3
Efficient way ever
DP to Pixel:
private int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Pixel to DP:
private int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Hope this will help you.
Solution 4
px to dp:
int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
.getDisplayMetrics());
Solution 5
Just call getResources().getDimensionPixelSize(R.dimen.your_dimension)
to convert from dp
units to pixels
Related videos on Youtube
Bram
Updated on November 12, 2021Comments
-
Bram over 2 years
I am trying to calculate a variable amount of pixels to density independent pixels and vice-versa.
This formula
(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
does not work on small devices because it is divided by zero.This is my dp to px formula:
px = (int)(dp * (displayMetrics.densityDpi / 160));
Could someone give me some pointers?
-
Padma Kumar over 12 yearsConverting dp units to pixel units developer.android.com/guide/practices/…
-
ct_rob over 12 years@Bram: I think your formula is just fine. How will you get a division by zero? displayMetrics.densityDpi will be either 120, 160, 240 or 320, never 0.
-
TomTaila over 7 yearsI agree with @ct_rob . displayMetrics.densityDpi / 160 minimum value will be 0.75. You must have been casting to int in the incorrect place.
-
-
ct_rob over 12 yearsalthough, now that i think about it...how will there ever be a divsion by zero in Brams original formula? displayMetrics.densityDpi will be either 120, 160, 240 or 320, never 0.
-
Admin over 12 years
(displayMetrics.densityDpi / 160)
- this part can get 0 on small devices, there it calculates for example120/160
, both values are int, which results in 0. Which ends up as(int) (px/0)
. -
ct_rob over 12 yearsah, you're right. So all he needs to do is use a long in his formula: 160.0
-
Kelly Copley almost 12 years@Vame The adding of 0.5 is used to round UP to the nearest integer value.. The 0.5 is added and then the result of the calculation is cast as an int causing it to truncate the mantissa and leaving characteristic as a properly rounded integer value.
-
PaNaVTEC about 11 yearsThis is from DP to PX, but with this correction:
typedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, valueInDp , getResources() .getDisplayMetrics());
is from PX to DP, also this is the best answer -
Marek about 11 yearsThis is not always correct. When I have two layouts one inside another and then I round corners of each view (one by using dp, other converting to dp) corners doesn't match!
-
Bram about 11 yearsI didn't have any problems with this technique. I used this for different layouts and it always worked as expected. Of course I used this few years ago and I am not sure if it still works. Perhaps you could try the other technique in PanaVTEC's answer. It could also be that there is more to rounding corners than just dp / px calculations.
-
Bachi almost 11 yearsthe
density
value is not exact, but rather adjusted in steps. From the docs:This value does not exactly follow the real screen size (as given by xdpi and ydpi, but rather is used to scale the size of the overall UI in steps based on gross changes in the display dpi. For example, a 240x320 screen will have a density of 1 even if its width is 1.8", 1.3", etc.
. If you need an exact conversion, better usedisplayMetrics.xdpi and displayMetrics.ydpi
(see my example below) -
alocaly about 10 yearsIt's the same solution that is adopted on the Android developer site, so I guess it's correct :) . http://developer.android.com/guide/practices/screens_support.html#dips-pels
-
nibarius about 10 yearsThis will not calculate the correct value for dp/px on many devices (including your Nexus 10)! As you say displayMetrics.density is rounded to the nearest screen bucket, but so is the dp unit! Try drawing one object that is 160dp wide and just below it you draw another object that is dpToPx(160) pixels wide and you will see that the size of the two objects are different. Also some phones (such as Galaxy Mini and Galaxy S3 Mini) report completely wrong values for xdpi/ydpi so on these phones your methods will return completely wrong results.
-
Bachi about 10 years@nibarius Yes you cannot mix Android's boxed dp calculations with the above. The above solution is meant as a separate density independent value based on the exact device physics. Needed eg where you want to show a line the exact same real length on different devices. Of course if the xdpi/ydpi inputs are not correctly set by some devices, it wont't work there.
-
nibarius about 10 yearsThanks for the clarification, when you need a fixed physical size this is the way to go.
-
Mark McClelland about 10 yearsxdpi and ydpi should not be used, because they are inaccurate on many devices, sometimes by a lot. Only DisplayMetrics.densityDpi is reliable, which is unfortunate, since it is imprecise by design. See Google forum thread for more info: groups.google.com/forum/#!topic/android-developers/g56jV0Hora0
-
Bahadır Yıldırım about 10 yearsI prefer this one as it includes xxhdpi and xxxhdpi and other units of measure.
-
william gouvea almost 10 yearsI found this response and actually used many similar solutions but I just went through the docs and found getDimensionPixelOffSet with given a dimension(declared in dip/dp) returns the offset in pixels just like the handmade code. I tested and worked flawlessly. Hope it helps!
-
Simon Dorociak over 9 years+1 Thanks man. Worked like a charm! Thank you for sharing this solution with us.
-
Stephen Niedzielski about 9 years@PaNaVTEC, the solution you referenced for dp to px is incorrect.
applyDimension
only yields pixels. See android.googlesource.com/platform/frameworks/base/+/refs/heads/… wherein no conversion is performed forCOMPLEX_UNIT_PX
. -
CJBS almost 9 yearsPer the documentation, this is the same as getDimension(), except the returned value is converted to integer pixels for use as a size. A size conversion involves rounding the base value, and ensuring that a non-zero base value is at least one pixel in size.
-
いちにち about 8 yearsJust to clarify that this method will not always give the correct value. Use the accepted answer instead.
-
Bram almost 8 yearsnice addition to the given solutions.
-
Lorne Laliberte almost 8 yearsI would be surprised if the conversion calculation wasn't at least as fast as a map lookup, not to mention a synchronized one. Do you have any test results to demonstrate this optimization is beneficial? On Android where working memory is limited, trading memory for calculation effort isn't something you should do without good reason.
-
bitbybit almost 8 yearsThis answer is plain wrong. It returns final values in pixels, never in
dp
. If you look at the source code, for the caseTypedValue.COMPLEX_UNIT_DIP
,value * metrics.density
is returned, where you actually needvalue * metrics.density
. So what you are getting` valueInDp` is NOT indp
forvalueInPx
inpx
. -
bitbybit almost 8 years^typo, I meant "...where you actually need
value / metrics.density
" -
Ayaz Alifov over 7 yearsBetter because there is no need to use Context :) Thanks.
-
Rik van Velzen almost 7 yearsMehhh, this doesn't give correct value. Try: Resources r = getResources(); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, r.getDisplayMetrics()); As described here: stackoverflow.com/questions/4605527/converting-pixels-to-dp
-
John smith over 6 yearsthis answer is similar to upper one because of DisplayMetrics.DENSITY_DEFAULT has 160 value. but can you please let us know what is DPI here how we calculate it.
-
Bram over 6 years@CelalOzanBerkYavuz could you elaborate what does not work?
-
toom almost 6 yearsBest answer! Unfortunately the "Marked as correct" answer is wrong. Especially since it uses
displayMetrics.xdpi
which is different on any device. Sadly, this wrong answer additionally has the most upvotes. -
user924 over 5 yearswhy are you hardcoding
displayMetrics.xdpi
? this answer doesn't use xdpi: stackoverflow.com/a/8490361/7767664 -
user924 over 5 yearsthis should be easier
(int) ((dp * App.getContext().getResources().getDisplayMetrics().density) + 0.5)
-
Raphael C over 4 yearsnice. should be marked as best answer. kotlin:
private fun dpToPx(dp: Int) = (dp * Resources.getSystem().displayMetrics.density).toInt()
-
EpicPandaForce about 2 yearsNot better,
Resources.getSystem()
is not always correct -
EpicPandaForce about 2 yearsApparently
return dp * context.getResources().getDisplayMetrics().density;
works -
Pang about 2 yearsLink in answer is dead - "The domain Skinkers.com may be for sale. Click here to inquire about this domain."
-
Malwinder Singh about 2 yearsWhy negative vote?