Programmatically set height on LayoutParams as density-independent pixels
Asked Answered
J

5

127

Is there any way to set the height/width of a LayoutParams as density-independent pixels (dp)? It looks like the height/width, when set programmatically, are in pixels and not dp.

Jones answered 11/5, 2011 at 5:56 Comment(0)
I
275

You need to convert your dip value into pixels:

int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, <HEIGHT>, getResources().getDisplayMetrics());

For me this does the trick.

Ilyse answered 11/5, 2011 at 6:16 Comment(3)
I think that getActivity().getResources().getDimension(resourceID) do the correct converting operations.Mirilla
Works for me, but it differs... if I set the width/height of an ImageView using the method above vs. using the xml. In the XML I set 85dp while the method above needs "75" to produce the same size. Any idea why?Shushubert
@Shushubert There is probably a padding/margin issue when you set it programatically (usually you have to specify the padding yourself when you set in code). There should be not difference whatsoever between setting dp in XML or in code.Meshwork
B
11
 public static int getDPI(int size, DisplayMetrics metrics){
     return (size * metrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;        
 }

Call the function like this,

DisplayMetrics metrics;
metrics = new DisplayMetrics();         
getWindowManager().getDefaultDisplay().getMetrics(metrics);

int heigh = getDPI(height or width, metrics);
Bit answered 11/5, 2011 at 6:1 Comment(2)
That is... really wrong. You have hard-coded to only support a fixed number of densities. If you want to scale by the density scaling factor, just multiply by developer.android.com/reference/android/util/… which would also be the same as doing (size * metrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT.Readjust
Yes your new answer is reasonable. Or as I said, just multiply by metrics.density. That is what it is for.Readjust
M
7

Since it may be used multiple times:

public static int convDpToPx(Context context, float dp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
}

I found it more practical to use the conversion rate, as usally more than one value has to be converted. Since the conversion rate does not change, it saves a bit of processing time.

/**
 * Get conversion rate from dp into px.<br>
 * E.g. to convert 100dp: px = (int) (100 * convRate);
 * @param context e.g. activity
 * @return conversion rate
 */
public static float convRateDpToPx(Context context) {
    return context.getResources().getDisplayMetrics().densityDpi / 160f;
}
Motch answered 8/2, 2015 at 22:2 Comment(0)
C
5

Here is my snippet:

public class DpiUtils {

    public static int toPixels(int dp, DisplayMetrics metrics) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
    }

}

where DisplayMetrics metrics = getResources().getDisplayMetrics()

Chlorite answered 17/1, 2015 at 9:44 Comment(0)
P
0

The answered solution didn't work for me, the height of the view was still off. I ended up with this, which works well:

protected int dp2px(int dp){
    final float scale = getResources().getDisplayMetrics().density;
    return (int) (dp * scale + 0.5f);
}

And if you want the other way round, pixels to dp ...

protected float px2dp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}
Packer answered 19/1, 2018 at 18:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.