55

Is it possible to set the Margins of a LinearLayout, programmatically but not with pixels, but dp?

Eurig Jones
  • 8,226
  • 7
  • 52
  • 74

6 Answers6

137

You can use DisplayMetrics and determine the screen density. Something like this:

int dpValue = 5; // margin in dips
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(dpValue * d); // margin in pixels

As I remember it's better to use flooring for offsets and rounding for widths.

Roman Mazur
  • 3,084
  • 1
  • 20
  • 24
  • just as a comment: you can also use TypedValue.applyDimensions() but it seems this way is better, see http://stackoverflow.com/questions/2406449/does-setwidthint-pixels-use-dip-or-px/2406790#2406790 (Romain Guy is an Android engineer) – bigstones Feb 06 '11 at 15:56
  • +1 - I have a couple widgets I built in code (not using XML), and you can only set pixels there. As soon as I specified SDK version, my layouts went crazy. I used this to fix them... Always use XML for Android layouts!!! – tpow Oct 19 '11 at 22:23
  • 1
    `Resources.getSystem().getDisplayMetrics().denisty` in case you are in a Util class that has no context. Got this from [here](https://stackoverflow.com/a/9563438/8383332) – Soon Santos Sep 26 '18 at 20:14
21

I had the same issue and used this technique to solve it:

First, I added an xml file to my res/values folder called dimensions.xml. It looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <dimen name="my_margin">5dip</dimen>
</resources>

Second, in my code, I got the pixel equivalent of that margin as follows (note I'm using Xamarin so this is C# code, but the pure Java version should be very similar):

int myMarginPx = Resources.GetDimensionPixelSize(Resource.Dimension.my_margin);

Finally, I create my layout params:

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FillParent, LinearLayout.LayoutParams.WrapContent);
layoutParams.SetMargins(myMarginPx, myMarginPx, myMarginPx, myMarginPx);
Steven
  • 316
  • 2
  • 5
  • in form of android java, it should be like: `int getDimenInt(Context context, @DimenRes int dimenRes){ return context.getResources().getDimensionPixelSize(dimenRes); }` – 刘宇翔 May 23 '17 at 02:38
9

You can convert dp to px, for example convert 5dp to px:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, r.getDisplayMetrics());
alexn
  • 91
  • 1
  • 3
3

The following method works for me for converting pixels to dp:

int pixelToDP(int pixel) {
    final float scale = RaditazApplication.getInstance().getResources().getDisplayMetrics().density;
    return (int) ((pixel * scale) + 0.5f);
}
IgorGanapolsky
  • 26,189
  • 23
  • 116
  • 147
1

convert DP to Pixel value

int Whatever_valueInDP=10;//value in dp
int Value_In_Pixel= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, Whatever_valueInDP, getResources()
                    .getDisplayMetrics());
Rahul_Pawar
  • 572
  • 1
  • 8
  • 16
0

Well for the kotlin guys i have got handy helper fun which works perfectly :)

fun setMarginsInDp(v: View, l: Int, t: Int, r: Int, b: Int) {
    if (v.layoutParams is ViewGroup.MarginLayoutParams){
        val screenDensity: Float = v.context.resources.displayMetrics.density
        val params: ViewGroup.MarginLayoutParams = v.layoutParams as ViewGroup.MarginLayoutParams
        params.setMargins(l*screenDensity.toInt(), t*screenDensity.toInt(), r*screenDensity.toInt(), b*screenDensity.toInt())
        v.requestLayout()
    }
}

Just pass in a valid view and all set up!

Ali Nawaz
  • 2,016
  • 20
  • 30