Understanding multiplier in auto layout to use relative positioning
I am trying to understand how one can utilize Auto Layout to position items relative to other views percentage-wise.
For example, I recently learned that you can specify a view’s bottom should lie 4% higher than its superview’s bottom by using this:
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 0.96, constant: 0))
This makes sense to me because a multiplier of 1 would align it right at the view’s bottom, so you can decrease that amount by 4 percent by changing the multiplier to 0.96.
But how can you do the same in the other direction? You want to specify a label’s top should begin 4% down from the superview’s top. If you use that same line but change the attributes to
.Top, that means it would be 4% higher than the superview’s top (but it actually doesn’t move it off screen). You can’t have a negative multiplier I don’t think, and I don’t believe a value greater than 1 does anything when constant is 0. So how do you get that set up?
I have the same question for implementing leading and trailing. Trailing is easy. If you want it 10% from the right:
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 0.9, constant: 0))
It makes sense because you dial it back 0.1 or 10% instead of aligning fully at 1.0. But how do you do the same for leading? I thought you might be able to set the label’s leading relative to the view’s trailing, then set the multiplier to 0.1. In my mind that would mean the label would start at the very far right but then be dialed back 90%, therefore obtaining the desired 10% from the left. But that’s not the case, I’m not sure why.
Can you explain how this is works, how to properly use multiplier to obtain these relative layouts?
To make it easy, let’s say you’d like to create a label that has top and bottom 10% of the superview’s height, and trailing and leading 10% of the superview’s width. On an iPhone in portrait there’s going to be more padding above and below the label than there is padding to the left and right of it, like so (yes it’s drawn to scale):
But let’s say on the iPad it’s going to be shown in a view that’s a perfect square. Therefore the padding will be the same amount all around, like so:
The question is how do you define such constraints to be dynamic in value, as opposed to setting a fixed value for a constant. I already know how to do bottom and trailing, but top and leading has me stumped. I’m hoping to understand how to use multiplier to do more advanced layouts, for example, specifying a label’s top should lie 10% beneath another label’s bottom, as opposed to setting it to a fixed constant.
- scrollView not scrolling all my contents
- AutoLayout to keep view sizes proportional
- UILabel sizeToFit doesn't work with autolayout ios6
- Autolayout ignores multi-line detailTextLabel when calculating UITableViewCell height (all styles)
- Adjusting views when Status Bar hides on rotation
- Using Auto Layout to have UILabel and UITextField next to each other
3 Solutions Collect From Internet About “Understanding multiplier in auto layout to use relative positioning”
There are a couple ways to do this. In the simplest case, you’ve already almost got it: if you want the horizontal boundaries to be at 10% and 90%, then you need to specify both constraints with respect to the trailing edge of the superview — so
Subview.Trailing locks to
Superview.Trailing with a multiplier of
0.9, as you say, but then
Subview.Leading also locks to
Superview.Trailing, just with a multiplier of
(and similarly for top / bottom)
On the other hand, the case you mention at the end is a little more complicated: “specifying a label’s top should lie 10% beneath another label’s bottom.” For that you probably won’t be able to use fixed percentage insets like the previous case. Instead, you can create an invisible spacer view between them: add a constraint with
Spacer.Height = 0.1 * Superview.Height and then attach it between the two labels. (You can also handle the previous case with these spacer views, but for that case it isn’t really necessary.)
In my opinion, “You can’t have a negative multiplier I don’t think, and I don’t believe a value greater than 1 does anything when constant is 0” exposed your comprehending deviation.
The rule underneath the hood is just a linear equation:
FirstItem.Attribute1 = (SecondItem.Attribute2 * Multiplier) + Constant
All measured in points. As you see, multiplier(a property of NSLayoutConstraint) is not the multiplier of constant. Follow the equation, what you don’t understand will be clear.
As to your specific example, @Archaeopterasa presented a great solution, another is shown below:
Based on the fact you know how to do bottom and trailing, I suppose you’ve done these two. Then add another two constraints, the effect will be what you want:
At last, if you want to specify a label’s top lie 10% beneath another label’s bottom, it seems that you cannot implement it without writing a line of code. You have to use code to set the constant of the NSLayoutConstraint object connecting the FirstItem and the SecondItem after the superview’s height is known in runtime.
Firstly, control drag from one label to the other and choose “Vertical Spacing”.(Or you can do this in other ways)
Secondly, a referencing outlet is needed:
@IBOutlet weak var tenPercentOfSuperview: NSLayoutConstraint!
Then, do this in a appropriate place(for example, in viewDidLoad())
let heightOfSuperview = self.view.bounds.height tenPercentOfSuperview.constant = heightOfSuperview * 0.1
Everything is OK now.
If you want to know more about this topic, Apple’s document is recommended:https://developer.apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/EditingConstraintAttributesintheAttributesInspector.html
way to do it:
Notice icon #1 is centered on the right end of the “View 1/4” helper view.
Notice icon #3 is centered on the left end of the “View 3/4” helper view.
You’re done, have a Chardonnay.
Conveniently, in the helper views, just set the multiplier to anything you want, depending on the feel wanted. It’s incredibly easy to then change those in your code, use IBInspectable, animate, and so on…
- Is it possible to launch another app in iOS 8 using Swift?
- How do I save a swift array?
- How to make custom keyboard only for my app in Swift?
- How to use enumerateDate in Swift 3 to find all Sundays the last 50 years?
- Getting Twitter profile image with Parse in Swift
- How to change entire copyright notice template for Xcode?
- Apple's description of reference and value types with multiple threads
- Valid file path for archiverootobject and unarchiverootobject
- Why is main window of type double optional?
- How do I dispatch functions in Swift the right way?
- How iPhone Contact app detect user has number linked to WhatsApp?
- Programmatically remove contact from adress book on specific time in swift
- Cannot open Xcode project on a new Mac
- Using iOS Dropbox SDK to do a Chunked Upload of Core Data
- NSDateFormatter dateFromString returns nil