A common UI pattern is to feature an image as the most important element in the center of the screen.
Creating The Pattern
Laying out the view with a label, imageView and a button and placing them in a vertical stack view
Pinning the stack view to the margins
Correcting The Pattern
AutoLayout is not using the frame that it should to correct this we can use Xcode's suggestions
After the corrections the view is still not exactly how we want it.
- The image view is not large enough
- The button is way too tall
- There is a lot of wasted space on the sides
To fix the wasted space issue we can modify the properties of the stack view by changing the alignment from Center
to Fill
To fix the button and image view issue we can modify the hugging and compression resistance properties to 249 and 749 respectively.
Lastly we need to make sure that the whole image is always shown and has the right proportions. To do this we change the content mode from Scale To Fill
to Aspect Fit
As a last touch we can add some spacing between the elements by increasing the spacing property on the stack view.
Creating A Header And Footer
To setup a header and footer we will have a set of views that make up the header as well as another set to make up the footer.
In the middle we will have a text view who's job will be to keep the header and footer apart
To build the header we add a label and an text field, and put then in a stack view. We repeat the process once more and then when finished put both of those stack views in a parent stack view.
To create the footer we create three buttons and place them in a stack view.
We place a text view in the middle of them.
And finally we place all of our elements and views inside a stack view and add the constraints needed to make it stick to the edges.
This is not quite what we want
Correcting The Header And Footer
We will need to correct 5 things
- The text fields and the header do not stretch across the screen
- There is no space between the stack views
- The footer button are distributed in a funky way
- The text view does not take enough vertical space
- The footer button also take too much vertical space
To fix the text fields in the header and make them stretch across the screen we need to change the alignment property on the vertical stack view from Leading
to Fill
To fix the lack of space between the stack views we select the root stack view and increase the spacing property from 0 to 8.
To fix the distribution and size of the footer buttons we need to change the alignment property of the footer stack view from Fill
to Fill Equally
. (We could also change to Equal Spacing
or Equally
which do roughly the same thing.)
- The
Fill
algorithm does not take intrinsic size into account and favors the first element*
The last issues are actually the same thing, the text view and the footer are fighting for space. And we want the text view to win the fight. By lowering the content hugging value of the text view we can resolve this issue.
There is just one small problem, there is no space between the label and the text fields in the header and no space between the two row in the header stack view.
To fix this we add spacing to both the header stack view and both of it's row stack views.
But by doing this we create another problem. The size of the first row in the header stack view is now smaller then the second. This is due to the Fill
distribution set on the header stack view.
To correct this we change the header stack view distribution from Fill
to Fill Equally
TextFields In AutoLayout
We want the text fields to all have the same width and be aligned vertically, regardless of the size of the label associated with them.
We create three horizontal stack views that each contain a label and a text field and wrap them all in a vertical stack view which has constrains to left top and right that pin it to the top of the view.
We change the vertical stack view alignment property to Fill
To adjust the text fields we need to connect views that are in different stack views.
One way to think about this would be to add constraints to the text fields but a more flexible and easier way to accomplish aligning the text fields and making them the same size would be to make all the labels the same size and allowing the remaining space to be given to the text fields.
You can see this best with frames enabled.
To relate views from different stack views we ctrl-click drag
from one element to another and in our case select Equal Widths
Square, Centered And Contained ImageView
Here we want the view to always keep the same aspect ratio, always be centered and take as much space as possible.
We add an image view, and to satisfy the aspect ratio requirement we need to add a constraint that relates the height and width of the image view.
To do this we ctrl-click drag
inside the image view and select Aspect Ratio
.
If you select it you can see the ratio
To fix this we change the Multiplier
property to 1:1
To satisfy the requirement that the image must be centered we ctrl-click drag
from the image view to the view and select Center Horizontally in Container
and Center Vertically in Container
At this point AutoLayout will complain because it does not know the size of the image.
In this case we want the image be contained within the edges of it's super view so the height and width must always be smaller or equal to the super view height and width.
We will need two constraints to accomplish this, to add them we ctrl-click drag
from the image view to the view and select Equal Width
and Equal Height
.
If you click on one of the constraints we just made and inspect it, the relationship is set to Equal
in this case we want to change that to Less Than or Equal
as the image can be much smaller then the super view if need be.
After all of this AutoLayout will still complain about not knowing the exact size of the image. It knows the maximum size but not the exact heigh and width. This can be corrected by adding an image to the image view in the attributes inspector.