Introduction
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.
![]() |
Navigator |
(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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ViewController: UIViewController { | |
// Set scroll view height to 35% of root view height // | |
let scrollViewHeightAsPercentageOfRootView : CGFloat = 0.36 | |
// Set scroll view width to 85% of root view width // | |
let scrollViewWidthAsPercentageOfRootView : CGFloat = 0.85 | |
let asvScrollView : UIScrollView = UIScrollView(frame: CGRectZero) | |
let asvContainerView : UIView = UIView(frame: CGRectZero) | |
let asvLeftView : UIView = UIView(frame: CGRectZero) | |
let asvMiddleView : UIView = UIView(frame: CGRectZero) | |
let asvRightView : UIView = UIView(frame: CGRectZero) | |
override func viewDidAppear(animated: Bool) { | |
super.viewDidAppear(animated) | |
// code placeholder tag // | |
} | |
/** | |
Installs subviews inside a scroll view container that defines the contents | |
and resizes proportionatly to the root view by leveraging autolayout. | |
*/ | |
func asvInstallSubviewsInsideTheScrollViewContainerWithConstraints() { | |
// code placeholder tag // | |
} | |
/** | |
Installs a scroll view without constraints. We delay the installation of the | |
constraints so that we can animate them into place later on in the code. | |
*/ | |
func asvInstallScrollViewWithoutConstraints() { | |
// code placeholder tag // | |
} | |
/** | |
Installs a scroll view container that resizes proportionatly to the root view | |
by leveraging autolayout. | |
*/ | |
func asvInstallScrollViewContainerWithConstraints() { | |
// code placeholder tag // | |
} | |
/** | |
Installs height and width constraints on our scroll view | |
*/ | |
func asvApplyHeightAndWidthConstraints() { | |
// code placeholder tag // | |
} | |
/** | |
Installs centering constraints on our scroll view | |
*/ | |
func asvApplyCenteringConstraints() { | |
// code placeholder tag // | |
} | |
/** | |
Installs label with blog name | |
*/ | |
func asvInstallBlogName() { | |
// code placeholder tag // | |
} | |
} |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let blogLabel : UILabel = UILabel() | |
let topLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: blogLabel, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier:1.0, constant: 64) | |
let leftLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: blogLabel, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0) | |
let rightLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: blogLabel, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0) | |
blogLabel.setTranslatesAutoresizingMaskIntoConstraints(false) | |
self.view.addSubview(blogLabel) | |
self.view.addConstraints([topLC,leftLC,rightLC]) | |
blogLabel.textAlignment = NSTextAlignment.Center | |
blogLabel.textColor = UIColor.darkGrayColor() | |
blogLabel.text = "aGupieWare" | |
blogLabel.font = UIFont(name: "Helvetica-Bold", size: 26) |
For the function asvApplyCenteringConstraints locate the comment "// code placeholder tag //" and replace it with the code below:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let centerXLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvScrollView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0) | |
let centerYLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvScrollView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0) | |
self.view.addConstraints([centerXLC,centerYLC]) |
Locate the function asvApplyHeightAndWidthConstraints and replace the comment "// code placeholder tag //" with the following lines of code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let heightLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvScrollView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.Height, multiplier: self.scrollViewHeightAsPercentageOfRootView, constant: 0) | |
let widthLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvScrollView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: self.scrollViewWidthAsPercentageOfRootView, constant: 0) | |
self.view.addConstraints([heightLC,widthLC]) |
Inside the function asvInstallScrollViewContainerWithConstraints locate the comment "// code placeholder tag //" and replace with the following code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Prevent system from creating layout constraints // | |
self.asvContainerView.setTranslatesAutoresizingMaskIntoConstraints(false) | |
// The width of the scrollable area is defined as one // | |
// and a half times that of the scroll view's width // | |
let widthRatio : CGFloat = 1.5; | |
// Add the container view and set its constraints so that // | |
// it resizes with the same proportions on screen rotations // | |
asvScrollView.addSubview(asvContainerView); | |
let topLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0) | |
let leadingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0) | |
let trailingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0) | |
let bottomLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0) | |
let widthLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Width, multiplier: widthRatio, constant: 0) | |
let heightLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvContainerView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvScrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0) | |
self.asvScrollView.addConstraints([topLC,leadingLC,trailingLC,bottomLC,widthLC,heightLC]) | |
self.asvContainerView.backgroundColor = UIColor.cyanColor() |
For the function asvInstallScrollViewWithoutConstraints replace the comment "// code placeholder tag //" with the following lines of code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Set scroll view properteis // | |
self.asvScrollView.backgroundColor = UIColor.brownColor() | |
self.asvScrollView.bounces = false | |
// Prevent the system from automatically assinging auto layout // | |
// constraints when adding our scroll view to the view hierarchy // | |
self.asvScrollView.setTranslatesAutoresizingMaskIntoConstraints(false) | |
self.view.addSubview(self.asvScrollView) |
Inside the function viewDidAppear replace the comment "// code placeholder tag //" with the following lines of code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Setup blog name // | |
self.asvInstallBlogName() | |
// Setup the scroll view // | |
self.asvInstallScrollViewWithoutConstraints() | |
// Setup the scroll view container // | |
self.asvInstallScrollViewContainerWithConstraints() | |
// Setup the scroll view container content views // | |
self.asvInstallSubviewsInsideTheScrollViewContainerWithConstraints() | |
// apply custom constraints to our scroll view // | |
self.asvApplyHeightAndWidthConstraints() | |
self.asvApplyCenteringConstraints() |
Replace the comment "// code placeholder tag //" inside the function asvInstallSubviewsInsideTheScrollViewContainerWithConstraints with the following lines of code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Prevent system from creating layout constraints // | |
self.asvLeftView.setTranslatesAutoresizingMaskIntoConstraints(false) | |
self.asvMiddleView.setTranslatesAutoresizingMaskIntoConstraints(false) | |
self.asvRightView.setTranslatesAutoresizingMaskIntoConstraints(false) | |
self.asvContainerView.addSubview(self.asvLeftView) | |
self.asvContainerView.addSubview(self.asvMiddleView) | |
self.asvContainerView.addSubview(self.asvRightView) | |
// Constrain the left subview to the left, top and bottom of its container view // | |
let leftTopLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvLeftView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0) | |
let leftBottomLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvLeftView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0) | |
let leftLeadingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvLeftView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0) | |
// Constrain the left subview's right side to the middle subview's // | |
// left side so that the two views are touching each other // | |
let leftTrailingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvLeftView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvMiddleView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0) | |
// Constrain the middle subview to the top and bottom of its container view // | |
let middleTopLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvMiddleView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0) | |
let middleBottomLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvMiddleView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0) | |
// Constrain the middle subview's right side to the right subview's // | |
// left side so that the two views are touching each other // | |
let middleTrailingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvMiddleView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvRightView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0) | |
// Constrain the right subview to the right, top and bottom of its container view // | |
let rightTopLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvRightView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0) | |
let rightBottomLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvRightView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0) | |
let rightTrailingLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvRightView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvContainerView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0) | |
// add the above constraints to the container view -- the // | |
// superview of the left, middle and right subviews // | |
self.asvContainerView.addConstraints([leftTopLC,leftBottomLC,leftLeadingLC,leftTrailingLC, | |
middleTopLC,middleBottomLC,middleTrailingLC, rightTopLC,rightBottomLC,rightTrailingLC]) | |
// Constrain the left, middle and right subviews so that they all have equal width. // | |
// we set the 'multiplier' to 0.99,-slightly widder middle view,- to eliminate a // | |
// a vertical line that appears to the left of the middle view. // | |
let leftMiddleWidthLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvMiddleView, attribute: NSLayoutAttribute.Width, multiplier: 0.99, constant: 0) | |
let rightMiddleWidthLC : NSLayoutConstraint = NSLayoutConstraint( | |
item: self.asvRightView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, | |
toItem: self.asvMiddleView, attribute: NSLayoutAttribute.Width, multiplier: 0.99, constant: 0) | |
// Add the width constraints from above // | |
self.asvContainerView.addConstraints([leftMiddleWidthLC,rightMiddleWidthLC]) | |
self.asvLeftView.backgroundColor = UIColor.blueColor() | |
self.asvMiddleView.backgroundColor = UIColor.yellowColor() | |
self.asvRightView.backgroundColor = UIColor.greenColor() |
Liftoff
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,
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// apply custom constraints to our scroll view // | |
self.asvApplyHeightAndWidthConstraints() | |
self.asvApplyCenteringConstraints() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -- animate the placements of our auto layout constraints -- // | |
// Place the scroll view slightly offset from center before animating // | |
self.view.layoutIfNeeded() | |
self.asvScrollView.center = CGPointMake(CGRectGetMidX(self.view.frame), CGRectGetHeight(self.view.frame)/8.0) | |
UIView.animateWithDuration(1.75, animations: { () -> Void in | |
// apply custom constraints to our scroll view // | |
self.asvApplyHeightAndWidthConstraints() | |
self.asvApplyCenteringConstraints() | |
self.view.layoutIfNeeded() | |
}) { (animated) -> Void in | |
// -- animation completion block -- // | |
// Once the initial animation is complete we animate the // | |
// contents of the scroll view by changing its content offset. // | |
self.asvScrollView.setContentOffset(CGPointMake(CGRectGetMaxX(self.asvLeftView.frame), 0), animated: true) | |
} |
Source:http://blog.agupieware.com/2014/12/auto-layout-and-uiscrollview-pure-auto.html
Tidak ada komentar:
Posting Komentar