简体   繁体   中英

why aren't auto layout constraints relative to the frame of UIViewController's view

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.

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 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.

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)

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM