Reputation: 1210
I am kind of confused about the whole auto constraint system. Why are constraints set to be constants?? If the point of having constraints is so that your views could be adaptive to different screen size, why aren't they set in terms of their relativity to the frame of self.view
.
Maybe a more concrete example can illustrate my point:
Suppose I have two views - view1
and view2
and view1
is above view2
in IB. When I set their vertical spacing constraints in IB, I will get something like:
(for view2) Top Space to: view1 ; Equals: 39
What confuses me is, why isn't it something like this:
Top Space to: view1 ; Equals: 0.2 * self.view.bounds.height
For when more constraints are added, constants aren't the best way to represent views's locations, when they are going to be rendered on different size screens.
Upvotes: 1
Views: 76
Reputation: 125007
Why are constraints set to be constants??
They're not necessarily just constants. A NSLayoutConstraint
has both a multiplier
and a constant
. The multiplier scales the constraint according to some attribute of another view, and the constant is added. From the docs:
item1.attribute1 = multiplier × item2.attribute2 + constant
That equation is probably the most important thing that you need to remember about layout constraints. You can see that you can make the constraint entirely relative to the second item's attribute, by setting constant
to 0, or you can make the constraint absolute and entirely ignore item2
by setting multiplier
to 0, or you can use them together.
If the point of having constraints is so that your views could be adaptive to different screen size, why aren't they set in terms of their relativity to the frame of self.view.
The point isn't just to adapt to different screen sizes -- you can use constraints to make interfaces that adapt to all sorts of things. And for that reason, you get to choose which objects to constrain to each other.
What confuses me is, why isn't it something like this:
Top Space to: view1 ; Equals: 0.2 * self.view.bounds.height
Using a multiplier like that is certainly possible with constraints. If you look at the NSLayoutConstraints
reference page, it's pretty easy to see how to set it up in code. To do it with the visual editor, create a constraint and then select it in the document outline. Use the Attributes inspector to adjust the multiplier
and constant
values to your liking (0.2 and 0, respectively, in your example).
Update: Looking at your example specifically, I don't think you can set up a top
constraint that depends on the superview's height
. The best reason I can think of for that, and it's largely speculation on my part, is that simply scaling your UI to match the screen size is a poor way to adapt your UI to different screens. If you use the screen size to position buttons, for example, you'll end up with great big buttons on a large device and little buttons on small one, and that doesn't make a lot of sense: users' fingers don't change size, and neither does the best size for reading text. I think the goal here is to encourage developers to adjust their UI to show more content on larger devices instead of showing bigger content.
Of course, there are some spacing issues that should change with the size of the device. For example, a 20px margin might be just right for your iPad app, but you'd rather go down to a 10px margin on small devices. For that kind of thing, it makes sense to use size classes, which let you use different layouts on different categories of devices. Your layouts should still use constraints as necessary to adapt to the specific device, but size classes address the fact that the UI for a large device is significantly different from what you want on a small one.
Also, know that you can easily adjust the values associated with constraints at runtime, even if you create the constraints visually. You can connect constraints to outlets in your view controller just as you would connect views to outlets. At run time, you can use the outlet to access the connected constraint and adjust the constant
or multiplier
values as you see fit.
Upvotes: 2
Reputation: 241
If you use storyboard, the distance between the two view usually constant. if you want constraints relative to the frame of UIViewController's view,you can set constraints in code。Like this :
override func viewDidLoad() {
super.viewDidLoad()
var view1 = UIView()
var view2 = UIView()
let sapce = self.view.frame.size.height * 0.1
let verticalSpacingConstraint = NSLayoutConstraint(item: view2,
attribute: NSLayoutAttribute.Top,
relatedBy: NSLayoutRelation.Equal,
toItem: view1,
attribute: NSLayoutAttribute.Bottom,
multiplier: 1,
constant: sapce)
}
Upvotes: 0