How can I create UIStackView with variable spacing between views?
SWIFT 4
Following lilpit answer, here is an extension of the UIStackView to add a top and a bottom spacing to your arrangedSubview
extension UIStackView {
func addCustomSpacing(top: CGFloat, bottom: CGFloat) {
//If the stack view has just one arrangedView, we add a dummy one
if self.arrangedSubviews.count == 1 {
self.insertArrangedSubview(UIView(frame: .zero), at: 0)
}
//Getting the second last arrangedSubview and the current one
let lastTwoArrangedSubviews = Array(self.arrangedSubviews.suffix(2))
let arrSpacing: [CGFloat] = [top, bottom]
//Looping through the two last arrangedSubview to add spacing in each of them
for (index, anArrangedSubview) in lastTwoArrangedSubviews.enumerated() {
//After iOS 11, the stackview has a native method
if #available(iOS 11.0, *) {
self.setCustomSpacing(arrSpacing[index], after: anArrangedSubview)
//Before iOS 11 : Adding dummy separator UIViews
} else {
guard let arrangedSubviewIndex = arrangedSubviews.firstIndex(of: anArrangedSubview) else {
return
}
let separatorView = UIView(frame: .zero)
separatorView.translatesAutoresizingMaskIntoConstraints = false
//calculate spacing to keep a coherent spacing with the ios11 version
let isBetweenExisitingViews = arrangedSubviewIndex != arrangedSubviews.count - 1
let existingSpacing = isBetweenExisitingViews ? 2 * spacing : spacing
let separatorSize = arrSpacing[index] - existingSpacing
guard separatorSize > 0 else {
return
}
switch axis {
case .horizontal:
separatorView.widthAnchor.constraint(equalToConstant: separatorSize).isActive = true
case .vertical:
separatorView.heightAnchor.constraint(equalToConstant: separatorSize).isActive = true
}
insertArrangedSubview(separatorView, at: arrangedSubviewIndex + 1)
}
}
}
}
Then you would use it like this:
//Creating label to add to the UIStackview
let label = UILabel(frame: .zero)
//Adding label to the UIStackview
stackView.addArrangedSubview(label)
//Create margin on top and bottom of the UILabel
stackView.addCustomSpacing(top: 40, bottom: 100)
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.