Basic iOS 8 Swift Animation using Core Animation

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
An iOS 8 Swift Graphics Tutorial using Core Graphics and Core ImageiOS 8 UIKit Dynamics – An Overview


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


The majority of the visual effects used throughout the iOS 8 user interface are performed using Core Animation. Core Animation provides a simple mechanism for implementing basic animation within an iOS application. If you need a user interface element to gently fade in or out of view, slide smoothly across the screen or gracefully resize or rotate before the user’s eyes, these effects can be achieved using Core Animation in just a few lines of code.

In this chapter we will provide an overview of the basics of Core Animation and work through a simple example. While much can be achieved with Core Animation, however, it should be noted that if you plan to develop a graphics intensive 3D style application then it is more likely that OpenGL ES or SceneKit will need to be used, a subject area to which numerous books are dedicated.


Contents


UIView Core Animation Blocks

The concept of Core Animation involves the use of so-called animation block methods. Animation block methods are used to mark the beginning and end of a sequence of changes to the appearance of a UIView and its corresponding subviews. Once the end of the block is reached, the animation is performed over a specified duration. For the sake of example, consider a UIView object that contains a UIButton connected to an outlet named theButton. The application requires that the button gradually fade from view over a period of 3 seconds. This can be achieved by making the button transparent through the use of the alpha property:

theButton.alpha = 0

Simply setting the alpha property to 0, however, causes the button to immediately become transparent. In order to make it fade out of sight gradually we need to place this line of code in a call to the animateWithDuration: animation block method as follows:

UIView.animateWithDuration(3.0, animations: {
        self.theButton.alpha = 0
}) 

A variety of properties may also be defined within the animation block. For example, the start of the animation can be delayed using the delay argument of the animateWithDuration(_:delay:options:animations:completion:) method call. The following example delays the start of the 3 second fade out animation sequence by 5 seconds:

UIView.animateWithDuration(3.0, delay: 5.0, 
	options: UIViewAnimationOptions.CurveLinear, 
	animations: { 
		self.theButton.alpha = 0   
	}, 
	completion: nil)
} 

Understanding Animation Curves

In addition to specifying the duration of an animation sequence, the linearity of the animation timeline may also be defined by specifying an animation curve setting for the options argument of the animateWithDuration class method. This setting controls whether the animation is performed at a constant speed, whether it starts out slow and speeds up and so on. There are currently four possible animation curve settings:

  • UIViewAnimationOptions.CurveLinear – The animation is performed at constant speed for the specified duration and is the option declared in the above code example.
  • UIViewAnimationOptions.CurveEaseOut – The animation starts out fast and slows as the end of the sequence approaches
  • UIViewAnimationOptions.CurveEaseIn – The animation sequence starts out slow and speeds up as the end approaches.
  • UIViewAnimationOptions.CurveEaseInOut – The animation starts slow, speeds up and then slows down again.

Receiving Notification of Animation Completion

Once an animation sequence has been committed and is underway it may be necessary to receive notification when the animation is completed so that the application code can, for example, trigger another animation sequence. This can be achieved by adding a code block to the completion: argument of the animateWithDuration class method call. The following code, for example, implements a completion handler to fade the button back into view after the fade out animation finishes:

UIView.animateWithDuration(3.0, delay: 5.0, 
	options: UIViewAnimationOptions.CurveLinear, 
	animations: { 
		self.theButton.alpha = 0   
	}, 
	completion: ({finished in
                if (finished) {
                    UIView.animateWithDuration(3.0, animations: {
                        self.theButton.alpha = 1.0
                    })
                }
            }))

Performing Affine Transformations

Transformations allow changes to be made to the coordinate system of a screen area. This essentially allows the programmer to rotate, resize and translate a UIView object. A call is made to one of a number of transformation functions and the result assigned to the transform property of the UIView object.

For example, to change the scale of a UIView object named myView by a factor of 2 in both height and width:

myView.transform = CGAffineTransformMakeScale(2, 2)

Similarly, the UIView object may be rotated using the CGAffineTransformMakeRotation() function which takes as an argument the angle (in radians) by which the view is to be rotated. The following code, for example, rotates a view by 90 degrees:

let angle = CGFloat(90 * M_PI / 180)
myView.transform = CGAffineTransformMakeRotation(angle)

The key point to keep in mind with transformations is that they become animated effects when performed within an animation block. The transformations evolve over the duration of the animation and follow the specified animation curve in terms of timing.

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Combining Transformations

Two transformations may be combined to create a single transformation effect via a call to the CGAffineTransformConcat() function. This function takes as arguments the two transformation objects that are to be combined. The result may then be assigned to the transform property of the UIView object to be transformed. The following code fragment, for example, both scales and rotates a UIView object named myView:

let scaleTrans = CGAffineTransformMakeScale(2, 2)
let angle = CGFloat(90 * M_PI / 180)
let rotateTrans = CGAffineTransformMakeRotation(angle)

myView.transform = CGAffineTransformConcat(scaleTrans, rotateTrans)

Affine transformations offer an extremely powerful and flexible mechanism for creating animations and it is just not possible to do justice to these capabilities in a single chapter. In order to learn more about affine transformations, a good starting place is the Transforms chapter of Apple’s Quartz 2D Programming Guide.

Creating the Animation Example Application

The remainder of this chapter is dedicated to the creation of an iOS application intended to demonstrate the use of Core Animation. The end result is a simple application on which a blue square appears. When the user touches a location on the screen the box moves to that location. Through the use of affine transformations, the box will rotate 180 degrees as it moves to the new location whilst also changing in size.

Begin by launching Xcode and creating a new Single View Application project named Animate using Swift as the programming language and with the Universal device option selected.

Implementing the Variables

For the purposes of this application we will need a UIView to represent the blue square and variables to contain the rotation angle and scale factor by which the square will be transformed. These need to be declared in the ViewController.swift file as follows:

import UIKit

class ViewController: UIViewController {

    var scaleFactor: CGFloat = 2
    var angle: Double = 180
    var boxView: UIView?
.
.
.

Drawing in the UIView

Having declared the UIView reference, we now need to initialize an instance object and draw a blue square located at a specific location on the screen. We also need to add boxView as a subview of the application’s main view object. These tasks only need to be performed once when the application first starts up so a good option is to use the viewDidLoad method in the ViewController.swift file:

override func viewDidLoad() {
    super.viewDidLoad()

    let frameRect = CGRectMake(20, 20, 45, 45)

    boxView = UIView(frame: frameRect)
    boxView?.backgroundColor = UIColor.blueColor()
    self.view.addSubview(boxView!)
}

Detecting Screen Touches and Performing the Animation

When the user touches the screen the blue box needs to move from its current location to the location of the touch. During this motion, the box will rotate 180 degrees and change in size. The detection of screen touches was covered in detail in An Overview of iOS 8 Multitouch, Taps and Gestures. For the purposes of this example we want to initiate the animation at the point that the user’s finger is lifted from the screen so we need to implement the touchesEnded method in the ViewController.swift file:

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
    let touch = touches.first as! UITouch
    let location = touch.locationInView(self.view)

    UIView.animateWithDuration(2.0, delay: 0.0,
        options: UIViewAnimationOptions.CurveEaseInOut, animations: {
            let scaleTrans = 
                 CGAffineTransformMakeScale(self.scaleFactor, 
                                            self.scaleFactor)
            let rotateTrans = CGAffineTransformMakeRotation(
                                    CGFloat(self.angle * M_PI / 180))

            self.boxView!.transform = 
                CGAffineTransformConcat(scaleTrans, rotateTrans)

            self.angle = (self.angle == 180 ? 360 : 180)
            self.scaleFactor = (self.scaleFactor == 2 ? 1 : 2)
            self.boxView?.center = location
        }, completion: nil)
}

Before compiling and running the application we need to take some time to describe the actions performed in the above method. First, the method gets the UITouch object from the touches argument and the locationInView method of this object is called to identify the location on the screen where the touch took place:

let touch = touches.first as! UITouch
let location = touch.locationInView(self.view)

The animation block class method is then called with an animation duration of 2 seconds and the curve set to ease in/ease out:

UIView.animateWithDuration(2.0, delay: 0.0,
    options: UIViewAnimationOptions.CurveEaseInOut, animations: {
.
.
.

Two transformations are then generated for the view, one to scale the size of the view and one to rotate it 180 degrees. These transformations are then combined into a single transformation and applied to the UIView object:

let scaleTrans = CGAffineTransformMakeScale(self.scaleFactor, 
					         self.scaleFactor)
let rotateTrans = CGAffineTransformMakeRotation(
                                    CGFloat(self.angle * M_PI / 180))

self.boxView!.transform = CGAffineTransformConcat(scaleTrans, 
  						       rotateTrans)

Ternary operators are then used to switch the scale and rotation angle variables ready for the next touch. In other words, after rotating 180 degrees on the first touch the view will need to be rotated to 360 degrees on the next animation. Similarly, once the box has been scaled by a factor of 2 it needs to scale back to its original size on the next animation:

self.angle = (self.angle == 180 ? 360 : 180)
self.scaleFactor = (self.scaleFactor == 2 ? 1 : 2)

Finally, the location of the view is moved to the point on the screen where the touch occurred:

self.boxView?.center = location

Once the touchesEnded method has been implemented it is time to try out the application.

Building and Running the Animation Application

Once all the code changes have been made and saved, click on the run button in the Xcode toolbar. Once the application has compiled it will load into the iOS Simulator (refer to Testing Apps on iOS 8 Devices with Xcode 6 for steps on how to run the application on a physical iOS device).

When the application loads the blue square should appear near the top left hand corner of the screen. Click (or touch if running on a device) the screen and watch the box glide and rotate to the new location, the size of the box changing as it moves:


Ios 8 core animation running.png

Figure 60-1

Summary

Core Animation provides an easy to implement interface to animation within iOS 8 applications. From the simplest of tasks such as gracefully fading out a user interface element to basic animation and transformations, Core Animation provides a variety of techniques for enhancing user interfaces. This chapter covered the basics of Core Animation before working step-by-step through an example to demonstrate the implementation of motion, rotation and scaling animation.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
An iOS 8 Swift Graphics Tutorial using Core Graphics and Core ImageiOS 8 UIKit Dynamics – An Overview