347

I'm doing:

button.setLayoutParams(new GridView.LayoutParams(65, 65));

According to the docs the units for the width and height (both 65 in the above) are "pixels". How do you force this to be device independent pixels, or "dp"?

0

7 Answers 7

586

You'll have to convert it from dps to pixels using the display scale factor.

final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
Sign up to request clarification or add additional context in comments.

12 Comments

The correct conversion is (int) (dps * scale + 0.5f). This is the formula we use throughout the framework.
The formula is in the docs. For further reading, go to section 3 of developer.android.com/guide/practices/…
@RomainGuy, can you please add a utility function to the API to convert from dp to px? Thanks.
what is dps here? im getting "dps cannot be resolved to a variable" error? what type of "dps" need to declare??
The "dps" variable is the input value that you want to convert.
|
278

I know this is an old question however I've found a much neater way of doing this conversion.

Java

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());

Kotlin

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)

6 Comments

Well done for finding out how to do this. I'm not a fan of repeating a formula in several places! Thanks.
If not, then create function with the formula
@Kenobi It does the conversion for you from DP to PX. The 65 above is the DP value you want converted to PX
This should be the accepted answer, not the current one where these number (0.5) coming magically from no where
@Johny19 The 0.5 is not magic. It's just how to round a floating point number to the nearest integer instead of truncating it. See my comment on Robby Pond's answer for more detail.
|
48

simplest way(and even works from api 1) that tested is:

getResources().getDimensionPixelSize(R.dimen.example_dimen);

From documentations:

Retrieve a dimensional for a particular resource ID for use as a size in raw pixels. This is the same as getDimension(int), 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.

Yes it rounding the value but it's not very bad(just in odd values on hdpi and ldpi devices need to add a little value when ldpi is not very common) I tested in a xxhdpi device that converts 4dp to 16(pixels) and that is true.

Comments

45

Looking at your requirement, there is alternate solution as well. It seems you know the dimensions in dp at compile time, so you can add a dimen entry in the resources. Then you can query the dimen entry and it will be automatically converted to pixels in this call:

final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);

And your dimens.xml will have:

<dimen name="dimen_entry_in_dp">72dp</dimen>

Extending this idea, you can simply store the value of 1dp or 1sp as a dimen entry and query the value and use it as a multiplier. Using this approach you will insulate the code from the math stuff and rely on the library to perform the calculations.

2 Comments

Note that the return value is actually an int, so it gets cast to a float.
This is a bad answer because it is fare to be dynamic
7

Based on drspaceboo's solution, with Kotlin you can use an extension to convert Float to dips more easily.

fun Float.toDips() =
        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, resources.displayMetrics);

Usage:

(65f).toDips()

Comments

0

Kotlin Version

val scale: Float = resources.displayMetrics.density
val resizedInDp = (stream.videoWidth * scale + 0.5f).toInt()

Usage:-

val params: ViewGroup.LayoutParams = yourLayout!!.layoutParams
            val scale: Float = resources.displayMetrics.density
            params.width = (widthDp * scale + 0.5f).toInt() // dp to px
            params.height =
                (heightDp * scale + 0.5f).toInt() // setting height according to aspect ratio
            yourLayout!!.layoutParams = params

Comments

0

Simply you can use androidx.annotation

@Dimension(unit = Dimension.DP)
private static final int strokeWidth = 1; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.