Swift 2 examples – #8 Gestures Recognizers. Swipe, Tap, Rotate, Panning, etc.

This post is part of my collection: Swift 2 – For Beginners.

This example shows how gesture recognizers works.

Adding gestures programmatically

It is possible to add gesture recognizers programmatically to a view using the method addGestureRecognizer. To do that we can use these lines of code:

static func addSwipeGestureRecognizer(targetView: UIView, swipeDirection: UISwipeGestureRecognizerDirection, actionTarget: AnyObject?, action: Selector){
        // Create gesture recognizer
        let swipeRecognizer = UISwipeGestureRecognizer(target: actionTarget, action: action)
        
        // Set swipe direction
        swipeRecognizer.direction = swipeDirection
        
        // Add recognizer to target view
        targetView.addGestureRecognizer(swipeRecognizer)
}

Swipe

However you can also add gestures using “drag and drop” in your storyboard from the object library:
gestures

It is also possible to configure some parameters using XCode, i.e the swipe direction.
swipeDirection

Once you have your gesture in the storyboard you can select it and drag it to your ViewController to create the action that should be executed when the gesture was recognized.

    @IBAction func onViewSwipe(recognizer: UISwipeGestureRecognizer) {
        print("swipe down")
    }

Rotate

We can use the rotation gesture recognizer to rotate a view:

    @IBOutlet weak var ghostImage: UIImageView!

    // Rotate
    @IBAction func onGhostRotate(recognizer: UIRotationGestureRecognizer) {
        print("onGhostRotate \(recognizer.rotation)")

        // Apply gesture rotation to ghost view
        ghostImage.transform = CGAffineTransformRotate(ghostImage.transform, recognizer.rotation)

        // Reset recognizer rotation
        recognizer.rotation = 0
    }

rotatedGhost

Tap

Using a tap gesture recognizer and what we learnt before when can play a sound when the user tap our image:

@IBAction func onGhostTapped(sender: UITapGestureRecognizer) {
   let audioPath = NSBundle.mainBundle().pathForResource("punch", ofType: "mp3")!
   do  {
        // Initialize the player
        player = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath))
        // Play
        player.play()   
 
    } catch{
        print("Error creating audio player.")
    }    
}

Panning

The pan gesture recognizer allows us to drag and drop views in our application:

 @IBAction func onGhostPanning(recognizer: UIPanGestureRecognizer) {
        GestureHelper.applyGestureTranslationToGestureView(recognizer, parentView: self.view)
    }
static func applyGestureTranslationToGestureView(recognizer: UIPanGestureRecognizer, parentView: UIView){
        // Apply translation recognizer view
        if let recognizerView = recognizer.view {
            
            // Get recognized translation
            let translation = recognizer.translationInView(parentView)
            
            // Calculate new center
            let originalCenter = recognizerView.center
            recognizerView.center = CGPoint(x:originalCenter.x + translation.x, y:originalCenter.y + translation.y)
        }
        
        // Reset recognizer translation
        recognizer.setTranslation(CGPointZero, inView: parentView)
    }

Shake

There is not shake gesture recognizer, to do something when the user shake the phone we have to override the method motionEnded. This code resets the position and rotation of our ghost when the user shakes the phone:

    override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
        
        if event?.subtype == UIEventSubtype.MotionShake{
            // Reset initial position
            ghostImage.center = ghostInitialPosition
            // Reset rotation and scale
            ghostImage.transform = CGAffineTransform()
        }
    }

Complete example:

GestureHelper

import UIKit

public class GestureHelper {
    
    // this adds a helper in "code behind" normally you would do it adding the gesture using the storyboard and then the gesture action to the controller...
     static func addSwipeGestureRecognizer(targetView: UIView, swipeDirection: UISwipeGestureRecognizerDirection, actionTarget: AnyObject?, action: Selector){
        
        // Create gesture recognizer
        let swipeRecognizer = UISwipeGestureRecognizer(target: actionTarget, action: action)
        
        // Set swipe direction
        swipeRecognizer.direction = swipeDirection
        
        // Add recognizer to target view
        targetView.addGestureRecognizer(swipeRecognizer)
    }
    
    static func applyGestureTranslationToGestureView(recognizer: UIPanGestureRecognizer, parentView: UIView, inertia: Bool = true){
       
        // Apply translation recognizer view
        if let recognizerView = recognizer.view {
            
            // Get recognized translation
            let translation = recognizer.translationInView(parentView)
            
            // Calculate new center
            let originalCenter = recognizerView.center
            recognizerView.center = CGPoint(x:originalCenter.x + translation.x, y:originalCenter.y + translation.y)
            
            // Inertia
            if inertia && recognizer.state == UIGestureRecognizerState.Ended {
                
                // Get speed
                let velocity = recognizer.velocityInView(parentView)
                let magnitude = min(sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y)) / 10000, 0.1)
                
                // Calculate final point
                var finalPoint = CGPoint(
                    x:recognizerView.center.x + (velocity.x * magnitude),
                    y:recognizerView.center.y + (velocity.y * magnitude))
                
                // Consider bounds
                finalPoint.x = min(max(finalPoint.x, 0), parentView.bounds.size.width)
                finalPoint.y = min(max(finalPoint.y, 0), parentView.bounds.size.height)
                
                // Apply inertia animation
                UIView.animateWithDuration(0.5,
                    delay: 0,
                    options: UIViewAnimationOptions.CurveEaseOut,
                    animations: {recognizerView.center = finalPoint },
                    completion: nil)
            }
        }
        
        // Reset recognizer translation
        recognizer.setTranslation(CGPointZero, inView: parentView)
    }
}

ViewController

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var ghostInitialPosition: CGPoint = CGPoint();
    var player = AVAudioPlayer()

    @IBOutlet weak var ghostImage: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        ghostInitialPosition = ghostImage.center
    }
    
    // Swipe
    @IBAction func onViewSwipe(recognizer: UISwipeGestureRecognizer) {
        print("swipe down")
    }
    
    // Tap
    @IBAction func onGhostTapped(sender: UITapGestureRecognizer) {
        playPunchSound()
    }
    
    // Rotate
    @IBAction func onGhostRotate(recognizer: UIRotationGestureRecognizer) {
        print("onGhostRotate \(recognizer.rotation)")
        
        // Apply gesture rotation to ghost view
        ghostImage.transform = CGAffineTransformRotate(ghostImage.transform, recognizer.rotation)

        // Reset recognizer rotation
        recognizer.rotation = 0
    }
    
    // Panning
    @IBAction func onGhostPanning(recognizer: UIPanGestureRecognizer) {
        GestureHelper.applyGestureTranslationToGestureView(recognizer, parentView: self.view)
    }
    
    // Shake
    override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
        
        if event?.subtype == UIEventSubtype.MotionShake{
            // Reset initial position
            ghostImage.center = ghostInitialPosition
            // Reset rotation and scale
            ghostImage.transform = CGAffineTransform()
        }
    }
    
    func playPunchSound(){
        let audioPath = NSBundle.mainBundle().pathForResource("punch", ofType: "mp3")!
        
        do  {
            // Initialize the player
            player = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath))
            
            // Play
            player.play()
            
        } catch{
            print("Error creating audio player.")
        }
    }
}
Advertisements

Your feedback is important...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s