I\'m trying to add vertical lines, between labels inside a stack view all programatically.
The desired finish will be something like this image:
I c
Here's a more flexible UIStackView subclass that supports to arbitrary addition of arranged subviews and is suitable for those that need a clear background on their UIStackView and subviews to put on top of a UIVisualEffectView, like the picture below.
import UIKit
@IBDesignable class SeparatorStackView: UIStackView {
@IBInspectable var separatorColor: UIColor? = .black {
didSet {
invalidateSeparators()
}
}
@IBInspectable var separatorWidth: CGFloat = 0.5 {
didSet {
invalidateSeparators()
}
}
@IBInspectable private var separatorTopPadding: CGFloat = 0 {
didSet {
separatorInsets.top = separatorTopPadding
}
}
@IBInspectable private var separatorBottomPadding: CGFloat = 0 {
didSet {
separatorInsets.bottom = separatorBottomPadding
}
}
@IBInspectable private var separatorLeftPadding: CGFloat = 0 {
didSet {
separatorInsets.left = separatorLeftPadding
}
}
@IBInspectable private var separatorRightPadding: CGFloat = 0 {
didSet {
separatorInsets.right = separatorRightPadding
}
}
var separatorInsets: UIEdgeInsets = .zero {
didSet {
invalidateSeparators()
}
}
private var separators: [UIView] = []
override func layoutSubviews() {
super.layoutSubviews()
invalidateSeparators()
}
override func awakeFromNib() {
super.awakeFromNib()
invalidateSeparators()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
invalidateSeparators()
}
private func invalidateSeparators() {
guard arrangedSubviews.count > 1 else {
separators.forEach({$0.removeFromSuperview()})
separators.removeAll()
return
}
if separators.count > arrangedSubviews.count {
separators.removeLast(separators.count - arrangedSubviews.count)
} else if separators.count < arrangedSubviews.count {
separators += Array(repeating: UIView(), count: arrangedSubviews.count - separators.count)
}
separators.forEach({$0.backgroundColor = self.separatorColor; self.addSubview($0)})
for (index, subview) in arrangedSubviews.enumerated() where arrangedSubviews.count >= index + 2 {
let nextSubview = arrangedSubviews[index + 1]
let separator = separators[index]
let origin: CGPoint
let size: CGSize
if axis == .horizontal {
let originX = (nextSubview.frame.maxX - subview.frame.minX)/2 + separatorInsets.left - separatorInsets.right
origin = CGPoint(x: originX, y: separatorInsets.top)
let height = frame.height - separatorInsets.bottom - separatorInsets.top
size = CGSize(width: separatorWidth, height: height)
} else {
let originY = (nextSubview.frame.maxY - subview.frame.minY)/2 + separatorInsets.top - separatorInsets.bottom
origin = CGPoint(x: separatorInsets.left, y: originY)
let width = frame.width - separatorInsets.left - separatorInsets.right
size = CGSize(width: width, height: separatorWidth)
}
separator.frame = CGRect(origin: origin, size: size)
}
}
}
The result?