Reputation:
I want to programmatically divide my screen into three parts. Each part shall be a label with a backgroundColor and the width is set to be:
// Get the device width
self.view.bounds.width
The height must be dynamically. An example is in the image below. Each color is one part. The first part (the red part) must be attached to the top and the last part (the orange) must be attached to the bottom. And dependent on the label size inside each part the height shall be adjusted.
The blue part is always 100% and dependent of the red and orange part it subtracts from the blue part.
Anyone have any ideas of how to achieve this? Appreciate help!
Upvotes: 1
Views: 1554
Reputation: 22939
To do this is best to use AutoLayout, using NSLayoutConstraint
s. Here's some sample code (at the moment this is all in viewDidLoad
, which probably isn't the best thing to do, but I'll leave it up to you to organise the code.)
override func viewDidLoad() {
super.viewDidLoad()
// 1.
var topView: UIView = self.view
// Have as many labels as you want!
for i in 0..<numberOfLabels {
let label = UILabel()
// 2.
label.numberOfLines = 0
label.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(label)
// 3.
if i == 0 || i == numberOfLabels - 1 {
label.setContentHuggingPriority(UILayoutPriority.abs(1000), forAxis: UILayoutConstraintAxis.Vertical)
}
let widthConstraint = NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal, toItem: self.view, attribute: .Width, multiplier: 1.0, constant: 0.0)
// 4.
let heightConstraint = NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .GreaterThanOrEqual, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 20.0)
// 5.
let attribute: NSLayoutAttribute = i == 0 ? .Top : .Bottom
let topConstraint = NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .Equal, toItem: topView, attribute: attribute, multiplier: 1, constant: 0)
// 6.
if i == numberOfLabels - 1 {
let bottomConstraint = NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: 0)
self.view.addConstraint(bottomConstraint)
}
label.addConstraint(heightConstraint)
self.view.addConstraint(widthConstraint)
self.view.addConstraint(topConstraint)
topView = label
}
}
1. topView
is the view that the label
's NSLayoutAttribute.Top
will be related to. For example: the first label's top is related to its container view; the second label's top is related to the first label; the third label's top is related to the second view, and so on.
2. Set the number of lines to zero to allow for as many lines as required by label.text
.
3. Set the content hugging priority of the top and bottom labels to 1000
. This will cause the top and bottom labels to 'hug' the text because middle label(s), by default, have a hugging priority of 250
.
4. Create an NSLayoutConstraint
that sets the label
to be higher than 20 points because for preferredMaxLayoutWidth
to be set automatically the width and height of the label must be explicitly defined by NSLayoutConstraint
s.
5. This selects the attribute on topView
that will pin the label
to the topView
. For example: if creating the first label
, its top is pinned to the top of the container view. Otherwise, the top of the label
is pinned to the bottom of the label above it.
6. If it's the last label, pin its bottom edge to the bottom of the container view.
Here's the result:
Hope that answers your question.
Upvotes: 1