What is the correct way to specify dimensions in DIP from Java code?
Asked Answered
F

4

52

I found that it is possible to set dimensions of my interface elements in XML layouts using DIPs as in following fragment:

android:layout_width="10dip"

But all Java interface takes integer as arguments and there is no way to specify dimensions in DIPs. What is the correct way to calculate this?

I figured that I have to use property density of DisplayMetrics class but is this a correct way?

May I rely on this formula being always correct?

pixels * DisplayMetrics.density = dip

Is there a utility function for the conversion somewhere in Android?

Fontainebleau answered 10/2, 2010 at 17:22 Comment(0)
E
92

There is an existing utility method built called TypedValue.applyDimensions(int, float, DisplayMetrics) that does this.

Here's how to use it:

// returns the number of pixels for 123.4dip
int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
                     (float) 123.4, getResources().getDisplayMetrics());

There's a list of other types that you can use with it including COMPLEX_UNIT_SP, COMPLEX_UNIT_PT all found in the page I linked above. If you exclude the (int) typecast, you'll get the floating point number.

I encountered the same problem and found this through poking around the code.

Emulate answered 10/2, 2010 at 17:22 Comment(1)
This converts pixels into DIP rather than DIP into pixels which I believe is what the OP wanted. Certainly it was what I wanted. Which you do like so: (int)(desiredDIP * context.getResources().getDisplayMetrics().density)Teletypewriter
M
46

That is the correct formula there. Although DisplayMetrics.density is not a static member, so, according to the same document you alluded to, correct usage is:

// Maybe store this in a static field?
final float SCALE = getContext().getResources().getDisplayMetrics().density;

// Convert dips to pixels
float valueDips = 16.0f;
int valuePixels = (int)(valueDips * SCALE + 0.5f); // 0.5f for rounding
Malatya answered 10/2, 2010 at 17:22 Comment(2)
Thanks Roman, I somehow overlooked this part. There are two extra topic-related questions : - will the density be always equal for both dimensions ? It seems so (as this is just one value), but perhaps there is some other formula for calculating this. - isn't there any API to do the conversion for me ? Do I really have to write the following snipped in my code ? In XML layout code, it is possible to specify "dip" as unit, why it's not possible in Java API ?Fontainebleau
I think you can safely assume density being equal in both dimensions. Remember, DisplayMetrics.density is the logical density, not the actual screen density (which may slightly vary from the logical density). Regarding a conversion API, it's trivial to write a helper method like say, Util.dip that converts dip's to pixels for use in function calls. It's cleaner to handle units in Java that way anyway.Malatya
P
9

Using the display metrics density field, you can get a scaling factor to convert to/from dips. Use the Math.round method to convert from a float to an int without needing a cast or adding 0.5

// Converting dips to pixels
float dips = 20.0f;
float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = Math.round(dips * scale);

// Converting pixels to dips
int pixels = 15;
float scale = getContext().getResources().getDisplayMetrics().density;
float dips = pixels / scale;
Probably answered 10/2, 2010 at 17:22 Comment(1)
Math.round does do a cast. (int)Math.floor(a + 0.5f) is what Math.round does under the hood.Astylar
S
5

I think the best way is not to define any dimensions in code, but use the values/dimens.xml file instead. You can always define your dimension in the desired unit like:

<dimen name="my_layout_height">120dp</dimen>

and then refer to this in your Activity like:

getResources().getDimensions(R.dimen.my_layout_height);

This would return pixels after doing the necessary conversions. And also of course you can refer to this in your other XMLs like:

android:layout_width="@dimen/my_layout_height"
Spiccato answered 10/2, 2010 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.