swiftautolayoutios9uistackview

How can I create UIStackView with variable spacing between views?


I have a simple horizontal UIStackView with several UIViews stacked inside. My goal is to create variable spacing between views. I am well aware that I can create constant space between the subviews using "spacing" property. However my goal is to create variable space. Please note, if at all possible, I would like to avoid using invisible views that act as spacers.

The best I came up with was to wrap my UIViews in a separate UIStackView, and use layoutMarginsRelativeArrangement = YES to respect layout margins of my inner stack. I was hoping I could do something similar with any UIView without resorting to this ugly work-around. Here is my sample code:

// Create stack view
UIStackView *stackView = [[UIStackView alloc] init];
stackView.translatesAutoresizingMaskIntoConstraints = NO;
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.alignment = UIStackViewAlignmentCenter;
stackView.layoutMarginsRelativeArrangement = YES;

// Create subview
UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
// ... Add Auto Layout constraints for height / width
// ...
// I was hoping the layoutMargins would be respected, but they are not
view1.layoutMargins = UIEdgeInsetsMake(0, 25, 0, 0);

// ... Create more subviews
// UIView view2 = [[UIView alloc] init];
// ...

// Stack the subviews
[stackView addArrangedSubview:view1];
[stackView addArrangedSubview:view2];

The result is a stack with views right next to each other with spacing:

enter image description here


Solution

  • Update For iOS 11, StackViews with Custom Spacing

    Apple has added the ability to set custom spacing in iOS 11. You simply have to specify the spacing after each arranged subview. Unfortunately you can't specify spacing before.

    stackView.setCustomSpacing(10.0, after: firstLabel)
    stackView.setCustomSpacing(10.0, after: secondLabel)
    

    Still way better than using your own views.

    For iOS 10 and Below

    You could simply add a transparent views into your stack view and add width constraints to them.

    (Label - UIView - Label - UIView -Label)

    and if you keep distribution to fill, then you can setup variable width constraints on your UIViews.

    But I would consider if this is the right situation to use stackviews if that's the case. Autolayout makes it very easy to setup variable widths between views.