There are a number of different ways to approach this.
One approach - not using stack views:
- add your labels to a "container" view
- start with
x = 0
and y = 0
- loop through the labels, calculating a new
x
value (label width + desired spacing between labels)
- if the new
x
would be past the edge of the container, reset x = 0
and add desired height to y
to "move to the next row"
- after labels have been laid out, set the height of the container view
Here is a simple example:
class TagLabelsViewController: UIViewController {
let containerView: UIView = {
let v = UIView()
return v
}()
let tagNames: [String] = [
"First Tag",
"Second",
"Third Tag",
"Fourth",
"The Fifth Tag",
"Sixth",
"Seventh",
"Tag Eight",
"Here are some Letter Tags",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"Nine",
"Ten",
"Eleven",
"Tag Twelve",
"Tag 13",
"Fourteen",
"Fifteen",
"Sixteen",
"Seventeen",
"Eightteen",
"Nineteen",
"Last Tag",
]
var tagLabels = [UILabel]()
let tagHeight:CGFloat = 30
let tagPadding: CGFloat = 16
let tagSpacingX: CGFloat = 8
let tagSpacingY: CGFloat = 8
// container view height will be modified when laying out subviews
var containerHeightConstraint: NSLayoutConstraint = NSLayoutConstraint()
override func viewDidLoad() {
super.viewDidLoad()
// add the container view
view.addSubview(containerView)
// give it a background color so we can see it
containerView.backgroundColor = .yellow
// use autolayout
containerView.translatesAutoresizingMaskIntoConstraints = false
// initialize height constraint - actual height will be set later
containerHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: 10.0)
// constrain container safe-area top / leading / trailing to view with 20-pts padding
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
containerView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
containerView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
containerView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
containerHeightConstraint,
])
// add the buttons to the scroll view
addTagLabels()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// call this here, after views have been laid-out
// this will also be called when the size changes, such as device rotation,
// so the buttons will "re-layout"
displayTagLabels()
}
func addTagLabels() -> Void {
for j in 0..<self.tagNames.count {
// create a new label
let newLabel = UILabel()
// set its properties (title, colors, corners, etc)
newLabel.text = tagNames[j]
newLabel.textAlignment = .center
newLabel.backgroundColor = UIColor.cyan
newLabel.layer.masksToBounds = true
newLabel.layer.cornerRadius = 8
newLabel.layer.borderColor = UIColor.red.cgColor
newLabel.layer.borderWidth = 1
// set its frame width and height
newLabel.frame.size.width = newLabel.intrinsicContentSize.width + tagPadding
newLabel.frame.size.height = tagHeight
// add it to the scroll view
containerView.addSubview(newLabel)
// append it to tagLabels array
tagLabels.append(newLabel)
}
}
func displayTagLabels() {
let containerWidth = containerView.frame.size.width
var currentOriginX: CGFloat = 0
var currentOriginY: CGFloat = 0
// for each label in the array
tagLabels.forEach { label in
// if current X + label width will be greater than container view width
// "move to next row"
if currentOriginX + label.frame.width > containerWidth {
currentOriginX = 0
currentOriginY += tagHeight + tagSpacingY
}
// set the btn frame origin
label.frame.origin.x = currentOriginX
label.frame.origin.y = currentOriginY
// increment current X by btn width + spacing
currentOriginX += label.frame.width + tagSpacingX
}
// update container view height
containerHeightConstraint.constant = currentOriginY + tagHeight
}
}
The results:
It's pretty straight-forward, and with the comments in the code you should be able to adapt it to your needs.
If you want a "pre-built" solution, perhaps with more features, searching for
swift left aligned tags view
comes up with lots of matches. This one (I have nothing to do with it) looks interesting: https://github.com/ElaWorkshop/TagListView