iOSプログラミング with Swift 2


2016.07.13: created by

Swiftで Pinch Gesture を扱う (指の位置を取得する)

ジェスチャを扱うプログラムを考えます。 ここでは最もピンチを扱うプログラムを作成してみます。 この例では、ピンチの親クラスである UIGestureRecognizer のメソッドにアクセスして マルチタッチの位置を取得しています。


  1. Xcode を起動して "Create a new Xcode project" で "Single View Application" として新しいプロジェクトを開きます。 ここではプロジェクト名を SwiftGesturePinch としています。



  2. Main.storyboard 上の ViewController 上に ImageViewを配置します。



  3. ImageViewはデフォルトではジェスチャを認識しないように設定されていますので、 ジェスチャを認識するように変更(User Interaction Enabled, Multiple Touch をともにチェック)します。




  4. さらに、配置した ImageView の上に Pinch Gesture Recognizer を配置します。 ViewControllerの上部に Pinch Gesture Recognizer のアイコン が表示されたら正しく追加されています。



  5. Storyboard上の ViewController 上の ImageView を、 ViewController.swift 中に IBOutlet で myImage変数にconnectします。









  6. Storyboard上の Pinch Gesture Recognizerを、 ViewController.swift 中に Action で tapImageView関数にconnectします。 関数の引数の型である Type: の値を UIPinchGestureRecognizer にすることを忘れないように注意しましょう。









  7. ViewController.swift を変更します。
  8. プログラムの中で、ピンチ ジェスチャにおいて、 Began, Changed, Ended それぞれの状態で枠を表示します。 Ended な状態でのマルチタッチの位置を枠として rects に追加しています (この例では rects は特に活用していません)。

    ViewController.swiftに追加するコード(赤字部分)
    import UIKit
    
    class ViewController: UIViewController {
        var rects: [CGRect]?
        var backupImage: UIImage?
    
        @IBOutlet weak var myImageView: UIImageView!
        @IBAction func pinchImageView(sender: UIPinchGestureRecognizer) {
            var r: CGRect?
            if (sender.numberOfTouches() >= 2) {
                let p:CGPoint = sender.locationOfTouch(0, inView: myImageView)
                let q:CGPoint = sender.locationOfTouch(1, inView: myImageView)
                r = CGRect(x: min(p.x,q.x), y: min(p.y,q.y), width: abs(p.x-q.x), height: abs(p.y-q.y))
            }
            switch sender.state {
            case .Began:
                print("began \(r)")
                backupImage = myImageView.image
                if r != nil {
                    myImageView.image = makeUIImage(backupImage, r)
                 }
           case .Changed:
            print("changed \(r)")
            if r != nil {
                myImageView.image = makeUIImage(backupImage, r)
            }
           case .Ended:
                print("ended \(r)")
                if r != nil {
                    myImageView.image = makeUIImage(backupImage, r)
                    rects!.append(r!)
                }
            default:
                print("default \(r)")
             }
        }
        
        func makeUIImage(image: UIImage?, _ rect:CGRect?) -> UIImage {
            let sz:CGSize = myImageView.frame.size
            UIGraphicsBeginImageContext(sz)
            let context: CGContextRef = UIGraphicsGetCurrentContext()!
            if image != nil {
                image!.drawInRect(CGRectMake(0,0,image!.size.width,image!.size.height))
            }
            CGContextSetLineWidth(context, 1.0)
            CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0)
            if rect != nil {
                CGContextStrokeRect(context, rect!)
            }
            let img = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return img
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            rects = Array<CGRect>()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
    }
    
  9. プログラムを実行します。
  10. ImageViewの上でピンチした場所が、赤い枠として表示に追加されます。 ピンチ ジェスチャーは拡大縮小のためのジェスチャとして想定されているようですが、 ここでは親クラスの UIGestureRecognizer にアクセスすることでマルチタッチ(複数の指)の位置を取得しています。




  11. サンプルのプロジェクトはこちら。(Xcode 7.3.1版)


http://karel.tsuda.ac.jp