Showing posts with label UIScrollView. Show all posts
Showing posts with label UIScrollView. Show all posts

Auto Layout and UIScrollView: A “Pure Auto Layout Approach” iOS Tutorial in Swift

With the advent of Auto Layout to iOS, more and more of the applications that we write will incorporate this new technology. If you are not using Auto Layout, then you are most likely writing error prone code that does a lot of mathematics that adjust your views for various situations. Auto layout is math but without all the complexities of doing mathematics. It simplifies the mathmatical process by abstracting out the most arduous part of computing view geometries—namely, view geometry dependencies. Solving simultaneous equations is a thing of the past with Auto Layout. We now “simply” specify the relational attributes between view geometric properties and let Auto Layout do the rest! However, as we all know, the introduction of a new framework brings a new set of hurdles to the table. One of the major hurdles that we have encountered is learning how to speak Auto Layout. We need to be very precise when using this new API. Our most recent difficult encounter was learning how to apply Auto Layout to a UIScrollView so that it behaves in a predictable way.

In this tutorial, using a “pure Auto Layout approach,” we will programmatically create a UIScrollView with three subviews of UIView's. (See video below)

These three subviews, colored blue, yellow and green, will comprise the scrollable content area of our scroll view. The size and position of our scroll view will be animated into place by modifying its Auto Layout constraint values. The size of our scroll view (the view port) will be defined as a ratio of the width and height of the device's screen. The width of the scrollable area will be defined as one and a half times that of the scroll view's width. Our scroll view along with its subviews will dynamically resize to support both landscape and portrait view orientations, however, the ratio of the scrollable area to that of the scroll view's width will not change. If you are not familiar or in need of a refresher of these two technologies follow these links: UIScrollView, Auto Layout.

Setting Up
Download and boot-up the latest version of Xcode. From the Welcome screen, press (command+shift+1) if it's not visible, select the “Create a new Xcode project” from the option menu.

Welcome Screen

On the next menu, select "Single View Application" and click on the button labeled "Next."

Select Type of Application

For the following menu fill out all the fields as shown. For the "Organization Name" field you may type in the name of your organization instead.

Project Options

On the final menu for this setup you are prompted to select a location where this project will live. You are also given the option to place this project under source control using git. If you know how to use git then by all means use it! Otherwise uncheck the selection box where it reads "Source Control."

Code Structure
From the "Navigator" window, typically positioned to the left of Xcode, select the "Project Navigator" icon located in the top left corner.


(If you can't see the navigator window as shown in the figure above then you may need to unhide it. To do this, in the top right corner of Xcode you will find a button with three segments, select the left most segment to show or hide the "Navigator" window). Double click on the yellow folder labeled Auto Layout and Scroll View to reveal its contents. Select the file named ViewController.swift. In the text editor you will find the boilerplate source code that defines the subclass of this view controller. Replace all the code for the class definition with the following:

The code above is the entire skeletal code of our project. Code lines 4 and 5 define the height and width of our scroll view as a ratio of its the root view. The root view is the top most parent view in our view hierarchy; it fills the entire devices screen.

View Hierarchy
From the code snippet above, code lines 8 through 12 are the view objects that will comprise our project's complete view hierarchy. The asvContainerView object is a subview, or child view, of the asvScrollView object. The asvLeftView, asvMiddleView and asvRightView are sibling objects and subviews of asvContainerView. The sibling views are the objects that make up the visible contents of the scroll view.

Figure 5. View Hierarchy

Figure 5 is a visual representation of the described view hierarchy. The brown colored view is the asvScrollView object; the parent object of the views that sit in front of it. The cyan colored view is the asvContainerView object. The blue, yellow and green are the asvLeftView, asvMiddleView and asvRightView, respectively.

Meat and Potatoes
(Optioanal) The first function, asvInstallBlogName, that we define sets up a label for our blog's name. In this function, find the comment "// code placeholder tag //" and replace it with the following lines of code:

For the function asvApplyCenteringConstraints locate the comment "// code placeholder tag //" and replace it with the code below:

This function simply centers our scroll view, asvScrollView, object relative to it's root parent view.

Locate the function asvApplyHeightAndWidthConstraints and replace the comment "// code placeholder tag //" with the following lines of code:

In this function we simply install the height and width constraints on our scroll view, asvScrollView, object. As mentioned earlier, the height and width of this scroll view is a fixed ratio to that of its parent root view—the devices visible screen area.

Inside the function asvInstallScrollViewContainerWithConstraints locate the comment "// code placeholder tag //" and replace with the following code:

This function adds a scroll view container, our asvContainerView, as a subview of the root view along with Auto layout constraints so that it resizes proportionately to the various root view sizes.

For the function asvInstallScrollViewWithoutConstraints replace the comment "// code placeholder tag //" with the following lines of code:

In this function we install asvScrollView object as a subview of the root view, without constraints. We delay the installation of the constraints so that we can animate their installation into place later on in this tutorial.

Inside the function viewDidAppear replace the comment "// code placeholder tag //" with the following lines of code:

The first four lines of code sets up our view hierarchy by calling methods that we have stubbed out; we will later define these methods. The last two lines of code call our, stubbed out, custom methods that setup the height, width and centering constraints of our asvScrollView object.

Replace the comment "// code placeholder tag //" inside the function asvInstallSubviewsInsideTheScrollViewContainerWithConstraints with the following lines of code:

The above code installs subviews on our asvContainerView object. As mentioned earlier, these subviews comprise the visible content of our scroll view. We also setup Auto Layout constraints so that these subviews resize proportionately to their container view; a desired behavior when supporting various device screen sizes and device orientations—landscape and portrait modes. We also setup differing colors on these subviews to be able to readily discern between them.

Compile and run the application in any of the iPhone simulators. Once your application is running you should see on your simulators screen something similar to the image depicted in figure 6, while your simulator is in portrait mode.

Figure 6

After rotating you simulator to landscape mode you should see something similar to figure 7. Try to scroll the colored images from left to right.
Figure 7

Brief Animation
For our finishing touches we add a little bit of animation. Locate the following lines of code inside the viewDidAppear function,

and replace it with the following code:

This project can be found on GitHub.

We hope you enjoyed this tutorial. As always, comments, questions, suggestions and critique are welcome below.