How to add leading padding to view added inside an UIStackView
Asked Answered
O

12

205

This is my setup: I have an UIScrollView with leading,top, trialing edge set to 0. Inside this I add an UIStackView with this constraints:

stackView.centerYAnchor.constraintEqualToAnchor(selectedContactsScrollView.centerYAnchor).active = true  
stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

Inside the stack view I add some views.
My issue is that because of the constraints the first view added to stack view will also have leading edge = 0.

What are the ways that I could add some padding to the first view ? Without adjusting the scroll view constraints.

Optometrist answered 13/9, 2015 at 16:29 Comment(3)
would you mine changing the accepted answer? Tolga's answer seems much better.Fulbright
Please don't change the accepted answer. The accepted answer is much better. Tolga's answer does not state when to do these settings, does not take safeAreaLayoutMargins into account, and does not use the standard layout margin sizes. And it is not clear how to change the answer to do this properly.Unattended
The accepted answer and these comments are incredibly out of date. You can now simply set the padding in a UIStackView.Retiarius
T
34

The solution you have provided doesn't add a padding for your views inside your UIStackView (as you wanted in the question), but it adds a leading for the UIStackView.

A solution could be to add another UIStackView inside your original UIStackView and give the leading to this new UIStackVIew. Then, add your views to this new UIStackView.

Hint, you can do that completely using Interface Builder. In other words, no need to write code for it.

Tompion answered 15/9, 2015 at 8:32 Comment(0)
G
582

When isLayoutMarginsRelativeArrangement property is true, the stack view will layout its arranged views relative to its layout margins.

stackView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
stackView.isLayoutMarginsRelativeArrangement = true

But it affects all arranged views inside to the stack view. If you want this padding for only one arranged view, you need to use nested UIStackView

Greasepaint answered 9/10, 2015 at 6:19 Comment(8)
isLayoutMarginsRelativeArrangement is a getter, setter is layoutMarginsRelativeArrangement. I can't edit the answerSedimentary
@Sedimentary there is no difference between getter and setter function in Swift. But you are right, people who develop with Objective-C should use layoutMarginsRelativeArrangement instead. Official documentation: developer.apple.com/reference/uikit/uistackview/…Greasepaint
For Objective-C: stackView.layoutMargins = UIEdgeInsetsMake(0, 20, 0, 20); [stackView setLayoutMarginsRelativeArrangement:YES];Counterpane
Feb 2019, at midnight sitting at the office - Answers like these give me the strength to move forward. Thanks @tolppRootlet
Nice Solution THANKS!Isobaric
why is this answer not marked yet?Uri
Note that using full width anchor on a child view will cause an error when using left/right padding and similarly when using full height anchor with top/bottom paddingLianaliane
But why must it be a UIStackView when only adding padding to one child? I tried for hours to use a UIView for this purpose and it just wouldn't work.Piedadpiedmont
I
217

I have found that constraints don't work inside a Stack View, or they seem somewhat strange.

(Such as if I add leading/trailing constraint to selected on image stackview, that adds leading to collectionview too, but doesn't add trailing; and it be conflict for sure).

stackview inside stackview

To set layout margins for all views inside the stackview, select:

Stack View > Size Inspector > Layout Margins > Fixed

Note: "Fixed" option was formerly called "Explicit", as seen in the screenshots.

Then add your padding:

storyboard

If answered 28/6, 2016 at 17:10 Comment(5)
one of the things Apple hide. I hate how Xcode is the opposite of good, friendly and easy. ThanksDoorsill
Xcode keeps on crashing when I change those explicit layout margins. Filed a bug but they replied it was a duplicate.Erupt
That's what I couldn't find in the UI. Change Layout Margins to Explicit to see the fields for Stack View margins.Peahen
FYI XCode 9 now calls this "Fixed" instead of "Explicit".Worked
Also in Xcode 9, uncheck "Use Safe Area Layout Guides" in File inspector, which as of writing still causes a lot of problems in IB, and stick with normal Layout guides for your constraints.Astraea
T
34

The solution you have provided doesn't add a padding for your views inside your UIStackView (as you wanted in the question), but it adds a leading for the UIStackView.

A solution could be to add another UIStackView inside your original UIStackView and give the leading to this new UIStackVIew. Then, add your views to this new UIStackView.

Hint, you can do that completely using Interface Builder. In other words, no need to write code for it.

Tompion answered 15/9, 2015 at 8:32 Comment(0)
O
26

What worked for me is to add to stack view another UIView that's just a spacer (works at least with stackView.distribution = .Fill):

let spacerView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
stackView.addArrangedSubview(spacerView)
stackView.addArrangedSubview(viewThatNeedsSpaceBeforeIt)
stackView.addArrangedSubview(NextView)...
Oca answered 5/11, 2015 at 8:10 Comment(0)
V
9

If you only need leading padding, then you can set the stack view's Alignment to "Trailing" and then you will be free to specify unique Leading constraints on each of its contained subviews.

As a bonus, you can also set the stack view's alignment to "Center" and then you can use Leading and/or Trailing constraints to give each item its own padding on both sides.

Vellum answered 16/11, 2016 at 21:17 Comment(0)
M
8

Set your stackview alignment to "center". After that you can give every subview different leading and trailing.

Michaud answered 13/4, 2021 at 14:8 Comment(0)
Y
7

swift 3: You just need set offset by:

firstView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 200).isActive = true

Be sure this constraint set after you parentView.addArrangdSubView(firstView)

Yahairayahata answered 6/4, 2017 at 8:37 Comment(1)
This will move the entire stack by the provided constant.Helladic
M
3

The solution would be to have a regular view in the stack view to hold whatever views you are wanting to add constraints to, and then you can add constraints for your items that are relative to the views in the stack view. That way, your original views can have leading and trailing constraints within the stack view.

This can be done in the interface builder and programatically.

Mancuso answered 22/4, 2020 at 18:34 Comment(0)
S
1

This question already has good answers, One suggestion though, use spacing property to set the spacing between the views. For first and last views there can be two options, either set insets as @tolpp suggested or add constraint attaching to parent (stackview) with constant to add padding.

Shamble answered 18/1, 2019 at 4:8 Comment(0)
A
0

What we did was add transparent components (e.g., UIButton/UIView) as the first and last children of the UIStackView. Then set constrain the width of these invisible children to adjust the padding.

Admass answered 20/3, 2018 at 1:49 Comment(0)
O
0

A xib / storyboard trick is to add uiviews at start & end of the uistackview and add width constraints on it. Make it clear to be sure it's not showing up.

Outcaste answered 16/5, 2023 at 9:3 Comment(0)
O
-3

It seems that the solution was pretty simple. Instead of:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

I just wrote:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor, constant: 15).active = true
Optometrist answered 13/9, 2015 at 16:58 Comment(4)
actually your code adds a leading for the uistackview inside the urscrollview, it doesn't add a padding for your views inside your uistackview, (as the question states)Tompion
yeah, but I don't know if you can add padding, so this will work for me.Optometrist
as a first thought, you can another uistackview insiide your original uistackview and give the padding to it. then add your views to this new uistackview (you can do that completely by interface builder, no need to write code for it)Tompion
Yes, that will work. You can added as an answer and I will accept it.Optometrist

© 2022 - 2024 — McMap. All rights reserved.