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.
- Enumerating a view's NSLayoutConstraints in Swift?
- How to set subviews with AutoLayout in UIScrollView programatically?
- With Auto Layout, how do I make a UIImageView's size dynamic depending on the image?
- how can I use one storyboard for 4“ and 3.5” iphone screens with autolayout (ios6 + ios7)?
- How to resize a parent view based on the size of subviews layouted with Autolayout
- Creating Auto Layout constraints to topLayoutGuide and bottomLayoutGuide in code
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…
- Spritekit scale full game to iPad
- UILabel with basic rich text support
- Disable App Nap in MacOS 10.9 (Mavericks) application
- Compile OpenCV (2.3.1+) for OS X Lion / Mountain Lion with Xcode
- How to implement AVAudioPlayer Inside Singleton Method?
- Warning: Format string is not a string literal
- Key data not storing to iCloud with NSUbiquitousKeyValueStore.defaultStore
- Shadow effects on ImageView in iOS
- Swift 3 Open Link
- iPhone: maximumElapsedTimeForCachedLocation used to remove cache value of core location
- How to capture image with AVFoundation framework?
- Is it possible to use format strings to align NSStrings like numbers can be?
- When is the appropriate moment in rotation to change the Layout parameters of a UICollectionView
- How to Create a CGSize in Swift?
- deep copy for array of objects in swift