Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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):
enter image description here

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:
enter image description here

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.

like image 415
Jordan H Avatar asked Nov 17 '14 01:11

Jordan H


People also ask

What is multiplier and ratio in auto Layout in IOS?

multiplier property. If you set a view's width to 60, and multiplier to 1:2 (resulting in an auto-layout height of 120), the actual value of . multiplier will be 0.5. So, in my view, it depends on what feels more natural.

What is multiplier in Autolayout?

Multiplier is there for creating Proportional Constraint. Auto Layout calculates the first item's attribute to be the product of the second item's attribute and this multiplier . Any value other than 1 creates a proportional constraint.

What are constraints in Swift?

Auto Layout constraints allow us to create views that dynamically adjust to different size classes and positions. The constraints will make sure that your views adjust to any size changes without having to manually update frames or positions.


1 Answers

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 0.1:

enter image description here

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

like image 117
Archaeopterasa Avatar answered Oct 12 '22 10:10

Archaeopterasa