Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
124 views
in Technique[技术] by (71.8m points)

ios - Evenly space multiple views within a container view

Auto Layout is making my life difficult. In theory, it was going to be really useful when I switched, but I seem to fight it all of the time.

I've made a demo project to try to find help. Does anyone know how to make the spaces between views increase or decrease evenly whenever the view is resized?

Here are three labels (manually spaced vertically even):

image1

What I want is for them to resize their spacing (not the view size) evenly when I rotate. By default, the top and bottom views squish towards the center:

image2

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

LOOK, NO SPACERS!

Based on suggestions in the comments section of my original answer, especially @Rivera's helpful suggestions, I've simplified my original answer.

I'm using gifs to illustrate just how simple this is. I hope you find the gifs helpful. Just in case you have a problem with gifs, I've included the old answer below with plain screen shots.

Instructions:

1) Add your buttons or labels. I'm using 3 buttons.

2) Add a center x constraint from each button to the superview:

enter image description here

3) Add a constraint from each button to the bottom layout constraint:

enter image description here

4) Adjust the constraint added in #3 above as follows:

a) select the constraint, b) remove the constant (set to 0), c) change the multiplier as follows: take the number of buttons + 1, and starting at the top, set the multiplier as buttonCountPlus1:1, and then buttonCountPlus1:2, and finally buttonCountPlus1:3. (I explain where I got this formula from in the old answer below, if you're interested).

enter image description here

5) Here's a demo running!

enter image description here

Note: If your buttons have larger heights then you will need to compensate for this in the constant value since the constraint is from the bottom of the button.


Old Answer


Despite what Apple's docs and Erica Sadun's excellent book (Auto Layout Demystified) say, it is possible to evenly space views without spacers. This is very simple to do in IB and in code for any number of elements you wish to space evenly. All you need is a math formula called the "section formula". It's simpler to do than it is to explain. I'll do my best by demonstrating it in IB, but it's just as easy to do in code.

In the example in question, you would

1) start by setting each label to have a center constraint. This is very simple to do. Just control drag from each label to the bottom.

2) Hold down shift, since you might as well add the other constraint we're going to use, namely, the "bottom space to bottom layout guide".

3) Select the "bottom space to bottom layout guide", and "center horizontally in container". Do this for all 3 labels.

Hold down shift to add these two constraints for each label

Basically, if we take the label whose coordinate we wish to determine and divide it by the total number of labels plus 1, then we have a number we can add to IB to get the dynamic location. I'm simplifying the formula, but you could use it for setting horizontal spacing or both vertical and horizontal at the same time. It's super powerful!

Here are our multipliers.

Label1 = 1/4 = .25,

Label2 = 2/4 = .5,

Label3 = 3/4 = .75

(Edit: @Rivera commented that you can simply use the ratios directly in the multiplier field, and xCode with do the math!)

4) So, let's select Label1 and select the bottom constraint. Like this: enter image description here

5) Select the "Second Item" in the Attributes Inspector.

6) From the drop down select "Reverse first and second item".

7) Zero out the constant and the wC hAny value. (You could add an offset here if you needed it).

8) This is the critical part: In the multiplier field add our first multiplier 0.25.

9) While you're at it set the top "First item" to "CenterY" since we want to center it to the label's y center. Here's how all that should look.

enter image description here

10) Repeat this process for each label and plug in the relevant multiplier: 0.5 for Label2, and 0.75 for Label3. Here's the final product in all orientations with all compact devices! Super simple. I've been looking at a lot of solutions involving reams of code, and spacers. This is far and away the best solution I've seen on the issue.

Update: @kraftydevil adds that Bottom layout guide only appear in storyboards, not in xibs. Use 'Bottom Space to Container' in xibs. Good catch!

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...