288

I'm trying to use Java (not XML) to create a LinearLayout with buttons that fill the screen, and have margins. Here is code that works without margins:

LinearLayout buttonsView = new LinearLayout(this); buttonsView.setOrientation(LinearLayout.VERTICAL); for (int r = 0; r < 6; ++r) { Button btn = new Button(this); btn.setText("A"); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); // Verbose! lp.weight = 1.0f; // This is critical. Doesn't work without it. buttonsView.addView(btn, lp); } ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); setContentView(buttonsView, lp); 

So that works fine, but how on earth do you give the buttons margins so there is space between them? I tried using LinearLayout.MarginLayoutParams, but that has no weight member so it's no good. And it doesn't work if you pass it lp in its constructor either.

Is this impossible? Because it sure looks it, and it wouldn't be the first Android layout task you can only do in XML.

2
  • 1
    developer.android.com/reference/android/view/…, int, int, int) Instead of layoutParams.setMargins(30, 20, 30, 0); you put layoutParams.setMargins(30dp, 20dp, 30dp, 0dp); Commented Jan 9, 2012 at 17:40
  • 3
    setMargins takes int as arguments.. you can only provide "dp" using xml attributtes Commented Feb 1, 2012 at 8:05

11 Answers 11

522

Here is a little code to accomplish it:

LinearLayout ll = new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(30, 20, 30, 0); Button okButton=new Button(this); okButton.setText("some text"); ll.addView(okButton, layoutParams); 
Sign up to request clarification or add additional context in comments.

11 Comments

thanks for a to-the-point code sample - way more beneficial than just descriptions
It looks like the margin params are set in pixels. Any way to set them in dps?
@ArtemRussakovskii Like most functions in Android, they take pixels. I suggest a global utility function that converts dips to px. This is what I have done in all my apps. Android API sucks.
@MaxHowell That's what I ended up doing. It's incredible that basic things like that are missing sometimes.
@ArtemRussakovskii - use TypedValue.applyDimension(...) to convert DIP to PX. See stackoverflow.com/questions/2238883/…
|
63

So that works fine, but how on earth do you give the buttons margins so there is space between them?

You call setMargins() on the LinearLayout.LayoutParams object.

I tried using LinearLayout.MarginLayoutParams, but that has no weight member so it's no good.

LinearLayout.LayoutParams is a subclass of LinearLayout.MarginLayoutParams, as indicated in the documentation.

Is this impossible?

No.

it wouldn't be the first Android layout task you can only do in XML

You are welcome to supply proof of this claim.

Personally, I am unaware of anything that can only be accomplished via XML and not through Java methods in the SDK. In fact, by definition, everything has to be doable via Java (though not necessarily via SDK-reachable methods), since XML is not executable code. But, if you're aware of something, point it out, because that's a bug in the SDK that should get fixed someday.

7 Comments

Ha, ok I understand now. Was getting a bit lost in the layout system which is rather complicated. I don't think there's anyway to set layout_widgth/height at runtime.
And there's no way to set the style: stackoverflow.com/questions/2016249/…
I haven't had a problem with setting width and height at runtime via LayoutPararms. I terms of styles...yeah, well, there's a reason I don't use 'em. :-)
I want to know why it's such a PITA to programmatically generate a UI
Took me ages to realise, that infact a few days ago I imported the wrong LayoutParams that didnt support Margins... Reading these answers I decided to remove my import. There are over 10 options D: I went for linearLayout.LayoutParams. Works.
|
33

To add margins directly to items (some items allow direct editing of margins), you can do:

LayoutParams lp = ((ViewGroup) something).getLayoutParams(); if( lp instanceof MarginLayoutParams ) { ((MarginLayoutParams) lp).topMargin = ...; ((MarginLayoutParams) lp).leftMargin = ...; //... etc } else Log.e("MyApp", "Attempted to set the margins on a class that doesn't support margins: "+something.getClass().getName() ); 

...this works without needing to know about / edit the surrounding layout. Note the "instanceof" check in case you try and run this against something that doesn't support margins.

1 Comment

Its exactly I looking for.
25

Due to variation in device screen pixel densities its good to always use DIP unit to set margin programmatically. Like below_

//get resources Resources r = getResources(); float pxLeftMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics()); float pxTopMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics()); float pxRightMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics()); float pxBottomMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics()); //get layout params... LayoutParams params=new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); params.setMargins(Math.round(pxLeftMargin), Math.round(pxTopMargin), Math.round(pxRightMargin), Math.round(pxBottomMargin)); //set margin... yourLayoutTOsetMargin.setLayoutParams(params); 

Hope this will help.

Comments

13

I have set up margins directly using below code

LinearLayout layout = (LinearLayout)findViewById(R.id.yourrelative_layout); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT); params.setMargins(3, 300, 3, 3); layout.setLayoutParams(params); 

Only thing here is to notice that LayoutParams should be imported for following package android.widget.RelativeLayout.LayoutParams, or else there will be an error.

Comments

9
 MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams(); layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin); 

1 Comment

“While this code may answer the question, it is better to include the explanation of the code here.
7

Try this

 LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ); params.setMargins(left, top, right, bottom); yourbutton.setLayoutParams(params); 

Comments

5

Try this:

MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); params.width = 250; params.leftMargin = 50; params.topMargin = 50; 

Comments

3
/* * invalid margin */ private void invalidMarginBottom() { RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) frameLayoutContent.getLayoutParams(); lp.setMargins(0, 0, 0, 0); frameLayoutContent.setLayoutParams(lp); } 

you should be ware of the type of the view's viewGroup.In the code above, for example,I want to change the frameLayout's margin,and the frameLayout's view group is a RelativeLayout,so you need to covert to (RelativeLayout.LayoutParams)

Comments

0

Here a single line Solution:

((LinearLayout.LayoutParams) yourLinearLayout.getLayoutParams()).marginToAdd = ((int)(Resources.getSystem().getDisplayMetrics().density * yourDPValue)); 

Comments

0

Core-KTX:

 updateLayoutParams<RecyclerView.LayoutParams> { topMargin = 10 rightMargin = 10 bottomMargin = 10 leftMargin = resources.getDimensionPixelSize(R.dimen.left) } 

Instead of RecycleView, use whatever your view is on ViewGroup.

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.