Autolayout - When using NSLayoutAttributeCenterX what scale does the multiplier use?

When using the attribute, a NSLayoutAttributeCenterX

multiplier of 1 results in a center that matches the specified view. Increasing the value moves it to the left and decreases to 0, moves it to the right.

I was able to achieve roughly the results I want through trial and error (3 views evenly spaced across the super view) using multipliers of 2.5, 1 and 0.625. During the confusion, I found that 200 is centered on the left edge of the said view (also zooms in more than it does not move the view), and 0.5 is centered on the right edge (decreasing towards 0 moves the view further to the left).

quick whiteboard for visualization

So here are my questions:

  • what is it?
  • is there a formula I can use to accurately position the views this way, or will it be trial and error forever?
  • Why do they do it?
+3


source to share


2 answers


Figuring out what the center constraint means when the multiplier is not 1.0 is tricky. I have been experimenting in Xcode 6 and here are my findings.

The corresponding constraint has the form A.center.x = B.center.x * m + c

, where A

and B

are the considered types, m

is the constraint multiplier, and c

is the constraint constant.

Suppose B center.x

is fixed by some other constraint. Then I believe that autorun behaves as if it were using this algorithm:

  • Find the closest common ancestor of A and B. Name this common ancestor G.

  • Let bxg = Bx center in coordinate system G. You can compute this in code as CGFloat bxg = [G convertPoint:B.center fromView:B.superview].x

    .

  • Calculate axg = Desired x-center in G-coordinate system. CGFloat axg = bxg * m + c

    ...

  • Convert axg to coordinate system A.superview

    and save it as A.center.x

    .

Okay, so with all that in mind, how do we use center constraints to achieve your "evenly distributed views" goal? We don't.

Here's the problem. Suppose all three of your subs have the same width, w. (The problem is even more complicated if they have different widths.) And let's say the container view has width W. There are four margins (one to the left of the leftmost subview, one between the left subview and the middle subview, one between the middle subhead and the right subview. and one to the right of the right peep.)

So the field width should be (W - 3 w) / 4. Then we want to connect this to another constraint somehow. You wanted to use the center constraint, but for the sake of simplicity, consider constraining the left edge in the left view L. We want the constraint to be L.left = (W - 3 w) / 4. This limitation is too difficult for autolayout to handle directly. Autodetect constraints can only include two view attributes, but this is related to three.

The solution is to introduce spacer views. Let's start with our three desired areas:

initial views

I've already constrained each of these three subzones to 80x80 and vertically centered.

Now I will add four spacer views, shown in gray:

added spacer views



I have limited each spacer height and vertical center, but I do not have a limit on their width. Next, I will constrain all spacers to the same width:

equal widths

Then I will bind each leading and trailing edge of the spacer to its nearest neighbors by manually setting the constants to zero. This is how I make my first spacer:

dividing edges

I do the same for the other three pads. I will not show it here.

When I select a view controller and ask Xcode to update all frames, I get evenly spaced views:

frame updates

Since I don't really want the spacers to be visible at runtime, I'll select them and close them. The hidden views are still part of the layout.

hide spacers

Now what if the subviews don't have the same width? Let's change the width of the blue subset:

change the width of the blue subset

Automatic layout updates the frames so that the spacers continue to have the same width.

+10


source


I figured out that if you place a view aligned to the center of the supervisor X (and I believe this will be true for the Y-axis as well), you can calculate the multiplier factor from the expected center of view using this:

Coeff = superview.width / view.center.X * 0.5

      

I. You have a supervisor with width = 600, you need to place the view centered at 0.25 of the supervisor width, then the center of view = 150

Coeff = 600 / 150 * 0.5 = 2

      



If you want a symmetrical look then

Coeff = 600 / 450 *0.5 = 0.666

      

Therefore, if you know that the center of vision (CoV) is 0.25, then the formula would be:

Coeff = 1 / CoV * 0.5

      

0


source







All Articles