• 10 hours
  • Medium

Free online content available in this course.

Videos available in this course

Certificate of achievement available at the end this course

Got it!

Last updated on 2/4/19

Understand the view stack

Log in or subscribe for free to enjoy all this course has to offer!

We can see that we have a base view that can have subviews to present all the visual components to the user. To arrange those views according to the visual design we require, we need to position and size each view.

Positioning & Sizing

The position of each subview is relative to its superview. To manage positioning and sizing we need to learn a few elements:

  • Size is a composition of 2 components: length and width.

  • Point represents coordinates:  x and y.

  • Frame is a composition of the Origin and Size. Origin is a point that refers to the left top corner of a subview relative to the left top corner of its superview

  • Bounds is also a composition the Origin and Size. Origin of bounds is relative to the frame of the same view.  

To describe those in code we need to know the following data types:

  • CGSize describes a size.

  • CGPoint describes a point - Origin.

  • CGRect describes a rectangle - Frame and Bounds.

Those new types are structures.

What are structures? o_O

Frame and bounds are properties of a view:

view.frame
view.bounds

Origin and size are properties of both: frame and bounds:

view.frame.origin
view.frame.size
view.bounds.origin
view.bounds.size

Origin is a point, and a point has 2 properties to represent a position: x, y. And width and height are properties of size:

view.frame.origin.x
view.frame.origin.y
view.frame.size.width
view.frame.size.height
        
view.bounds.origin.x
view.bounds.origin.y
view.bounds.size.width
view.bounds.size.height

The end properties - x, y, width and height are of CGFloat that data type that is very correlated with Float and Double.

Variables for size and position

Frame, Bounds, Size and Origin are of structure data type and to create those we use the following syntax:

CGPoint(x: CGFloat, y: CGFloat)
CGPoint(x: Double, y: Double)
CGPoint(x: Int, y: Int)
        
CGSize(width: CGFloat, height: CGFloat)
CGSize(width: Double, height: Double)
CGSize(width: Int, height: Int)
        
CGRect(origin: CGPoint, size: CGSize)
CGRect(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)
CGRect(x: Double, y: Double, width: Double, height: Double)
CGRect(x: Int, y: Int, width: Int, height: Int)

 Other types in the example above are already familiar to you: Double and Int.

Let's look at some of the variable examples for the new structures:

// declare variables
let origin = CGPoint(x: 20.0, y: 10.0)
let size = CGSize(width: 50, height: 50)
let frame = CGRect(origin: origin, size: size)
let anotherFrame = CGRect(x: 20.0, y: 10.0, width: 50.0, height: 50.0)
        
// access properties
print(origin.x) // 20.0
print(size.width) // 50.0
print(frame.origin.y) // 10.0
print(anotherFrame.size.height) // 50.0

Notice that we have multiple initializers for these structures. They allow for the use of different datatypes, specifically: CGFloat, Double and Int

Regardless of the initializer we choose, the resulting properties (x, y, width and height) are always of CGFloat type, they are converted during the assigning process:

let double = 10.0
let x = CGFloat(double)

Let's illustrate all these properties and their relativity:

Frame & Bounds
Frame & Bounds

View A in the above illustration is the containing view for a subview B. Frame origin of view B is relative to view A. And bounds origin of view B is relative to itself (view B).

Let's review our example of views hierarchy from previous chapter:

Layout hierarchy
Layout hierarchy

And now let's shift some of the views around:

Expanded and overlapping views
Expanded and overlapping views

This illustration presents 2 new cases:

  • Views extended beyond bounds layout

  • Overlapping views 

Beyond bounds layout is when either a view has negative origin relative to its containing view, or a view is larger than its superview:

Beyond bounds layout
Beyond bounds layout

Parts of a view that extend beyond the bounds of a containing view may or may not be visible. It depends on whether the containing view has a restriction to not display subviews that lay beyond its own bounds. It's done using the property  clipsToBounds : 

view.clipsToBounds = true/false

Overlapping is when one subview is positioned within an area taken by another subview of the same superview:

Overlapping subviews
Overlapping subviews

In case of overlapping, a part of a view that is covered by another view may or may not be visible depending on the level of transparency of a covering view.

View A-2 is not transparent and it's making part of the A-1 view invisible. On the other hand, view A-4 is semi-transparent so that makes view A-3 still visible on the screen.

UI flow

We can nest multiple views with different layouts, including the full screen ones that would appear as completely different screens. That may become hard to manage within the one ViewController. Here's how it may look:

Managing UI flow on a single screen
Managing UI flow on a single screen

To address this we can create multiple base views, also called screens. Those views will then contain their own nested subviews in multiple layers. We will present different screens to the user depending on the user flow of an application. Those screens are created in the Storyboard by dragging new VewContoller objects from the Object Library:

Managing UI flow with multiple screens
Managing UI flow with multiple screens

Like with multiple trees in a garden, we can visit one or another as we please.

Let's Recap!

  • Views' layout is described using frame and bounds properties.

  • Both frame and bounds are represented by a composition of origins and size.

  • Frame origin is relative to its superview and bounds origin is relative to its frame.

  • The origin property is described with 2 properties that represent coordinates: x and y.

  • The size property is described with 2 properties that represent size: width and height.

  • Frame and Bounds are represented by a structure CGRect

  • Origin is represented by a structure CGPoint.

  • Size is represented by a structure CGSize.

  • Structures are named types, they are value types similar to classes but do not support inheritance. 

  • Multiple view controllers are used to generate multiple screens in the app to implement a required UI flow.

Example of certificate of achievement
Example of certificate of achievement