Reputation: 55665
I have programmatically created an auto layout constraint that moves a label up 25 points from the bottom of its parent view. There are no other constraints I define on this scene. 25 is fine on most devices, but it's too far up on the iPhone 4s. I would like to make it about 15 up from the bottom for that screen size. But then I was thinking it would be much better to obtain a variable constant instead of enforcing a fixed value for all screen sizes, or attempting to change it for one specific screen size. But it doesn't seem this is possible with Auto Layout. Is it?
I was thinking one way to obtain a variable constant would be to calculate a value based on the screen (or view) height. For example, the constant would be equal to self.view.frame.size.height / 30
. On iPhone 4 (portrait only) it would be 16, iPhone 5 it would be almost 19, etc. This would be perfect. Or another way, 3% of the height. These values would need to be dynamic for rotations though, as the height will change.
Is it possible to use auto layout constraints that have variable constants based on some calculation or screen/view height? Or is there some other solution that will allow me to obtain the desired behavior - avoiding fixed auto layout constants?
Here's some example code, from viewDidLoad
:
let footerLabel = UILabel()
footerLabel.text = "my text"
footerLabel.sizeToFit()
footerLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(footerLabel)
self.view.addConstraint(NSLayoutConstraint(item: footerLabel, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: -25))
self.view.addConstraint(NSLayoutConstraint(item: footerLabel, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1, constant: 0))
Upvotes: 2
Views: 4148
Reputation: 331
I was thinking one way to obtain a variable constant would be to calculate a value based on the screen (or view) height. For example, the constant would be equal to self.view.frame.size.height / 30. On iPhone 4 (portrait only) it would be 16, iPhone 5 it would be almost 19, etc. This would be perfect. Or another way, 3% of the height. These values would need to be dynamic for rotations though, as the height will change.
You can just change your first constraint to:
self.view.addConstraint(NSLayoutConstraint(item: footerLabel, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 0.97, constant: 1))
Keeping the constant 0 and changing the multiplier to 0.97 means the bottom of your label will always be 3% higher than the bottom of your view.
Upvotes: 1
Reputation: 8741
I would not assign the constraint directly to the view.
I would:
In viewDidLoad, use this function to initialize it:
Add the constraint to the view using self.view.addConstraint
Assign different values (using .constant) to that constraint when orientation changes or based on device.
Upvotes: 0
Reputation: 51911
You can setup "spacer" view with which height are constrained to 3% of the view
.
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
let spacer = UIView()
label.setTranslatesAutoresizingMaskIntoConstraints(false)
spacer.setTranslatesAutoresizingMaskIntoConstraints(false)
spacer.hidden = true
view.addSubview(spacer)
view.addSubview(label)
var views = ["spacer":spacer, "label":label]
view.addConstraint(NSLayoutConstraint(item: spacer, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.03, constant: 0))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[label][spacer]|", options: nil, metrics: nil, views: views))
view.addConstraint(NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0))
label.backgroundColor = UIColor.purpleColor()
label.text = "THIS IS MY LABEL"
}
Upvotes: 1