Learn UIStackView By Building An AirBnb App in XCode
A layout tool that will simplify your life
UIStackView was only added to Apple’s UIKit in IOS 9.0, making it the newest addition to the family — if it was still 2015. It doesn’t matter… because not only are they versatile in layout and underacknowledged imho, UIStackViews allow us to:
- Structure complex layouts without overcrowding our View Controller with constraints
- Make changes to our layout during runtime without painful constraint manipulation
- Views automatically adjust themselves (i.e. if you want to add animation)
Let’s demonstrate this by building a simple page inspired by AirBnb’s misleadingly complex layout:

Divide and Conquer
The key to building a page using stack views is in the ability to break down a layout into stack-able containers. There is no single combination for breaking down a layout into stacks as this procedure is dependent on the aesthetic preference of your page. The sample page above, for example, contains a hierarchy of nested horizontal and vertical stacks. First, let’s focus on the stacks contained in the red container.
Nested Stacks and Stacks with Padding

Notice the subtle left and right padding that applies to all elements under the main image. This effect can be achieved within the declaration of a vertical stack. For this reason, all views going into our “stack 4” — vertical stack with padding — will not require horizontal spacing constraints. Stacks require intrinsic content dimensions for all elements it contains unless the stack is explicitly constrained by its superview.
Among all the views going into “stack 4”, only three will be stacks. The rest of the views contained in the vertical stack will be the views themselves. These three nested stacks are labeled “stack 1” and “stack 2”, and “stack 3”.
1. “STACK 1” (nested horizontal stack)

- “Entire Home” label
- “Hosted by dotcookiez” label
- Profile Picture imageView
“Stack 1” consists of a regular vertical stack with 3pt equal spacing. A .leading alignment is needed for the labels to be left aligned as shown. Using my AutoLayoutExtensions class, this can be done using the line:
let stack1a = verticalStack(.leading, spacing: 3, views: homeLabel, hostedLabel)To combine the profile imageView with the vertical stack, create a horizontal stack using the returned vertical stack and the profile imageView. Remember that the profile image’s width and height must be constrained in order to be visible.
profileImage.setWidthAndHeight(65, heigh:65)
let stack1 = horizontalStack(.center, spacing: 0.0, views: stack3a, profileImage)2. “STACK 2” (nested horizontal stack)

- “5 guests” icon
- “2 rooms” icon
- “3 beds” icon
- “2 bath” icon
This nested stack is made out of four icons stacked horizontally with center alignment. Although the the spacing is set to 0 (the default spacing value), its width will later be constrained by the vertical stacks and so simply ensuring center alignment with equal spacing will do the automatic distribution trick.
guestsIcon.setWidthAndHeight(55, height: 55)
roomsIcon.setWidthAndHeight(55, height: 55)
bedsIcon.setWidthAndHeight(55, height: 55)
bathsIcon.setWidthAndHeight(55, height: 55)
let stack5 = horizontalStack(.center, spacing: 0, views: guestsIcon, roomsIcon, bedsIcon, bathsIcon)3. “STACK 3” (nested vertical stack)
It may seem counterintuitive at first to have a vertical stack nested inside another vertical stack. Note, however, that the spacing between the two labels inside “stack 3” differs from the spacing between all the elements that will be going into our vertical stack with padding. To mimic this effect, we will apply a spacing of 3pts to the views in this stack.

let stack7 = verticalStack(.fill, spacing: 3, views: aboutLabel, aboutText)4. “STACK 4”
- “Luxury Condo in Heart of Downtown” title label
- “stack 1”
- divider 1
- “stack 2”
- divider 2
- “stack 3”
Finally, all the views (except the main image) will go into the vertical stack with padding. Remember again that the dimensions of all the individual elements must be unambiguous so set all widths and heights as needed here. Using methods of the AutoLayoutExtensions, this will look like the following:
divider1.setHeight(1) // width will be constrained by the vertical stack with padding
divider2.setHeight(1)
/* STACK 3 */
let stack3 = verticalStack(.fill, spacing: 3, views: aboutLabel, aboutText)/* STACK 4 - Vertical Stack with Padding */
let stack4 = verticalStackWithPadding(.fill, spacing: 15, padding: UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20), views: titleLabel, stack1, divider1, stack2, divider2, stack3)
Putting it all together
Now that we’ve put all the elements besides the main image into one stack, we can finally add our main image. Simply do this with the line:
let finalStack = verticalStack(.center, spacing: 15, views: mainImage, stack4)
Remember when I said that all stacks require intrinsic content dimensions for all elements it contains unless the stack is explicitly constrained by its superview? Since all the views we initialized above depend on the stack’s horizontal constraint (they won’t know where the left and right borders are otherwise), this final line puts everything in place and ultimately allows everything to display properly.
