同时识别 UIPanGestureRecognizer、UIRotationGestureRecognizer 和 UIPinchGestureRecognizer

Simultaneously recognising UIPanGestureRecognizer, UIRotationGestureRecognizer, and UIPinchGestureRecognizer

我有以下代码可以同时识别平移、捏合和旋转手势识别器。问题是旋转视图时平移手势无法正常工作。在水平拖动旋转视图时,它也会不断向上移动。这是我的代码。

import UIKit

 class ViewController: UIViewController, UIGestureRecognizerDelegate {

     private var transformEditingView:UIView!

    override func viewDidLoad() {
         super.viewDidLoad()
        // Do any additional setup after loading the view.
    
         self.view.backgroundColor = UIColor.blue
    
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(transformViewGestureHandler(_:)))
        panGesture.delegate = self
        panGesture.maximumNumberOfTouches = 1
        self.view.addGestureRecognizer(panGesture)
    
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(transformViewGestureHandler(_:)))
        pinchGesture.delegate = self
        self.view.addGestureRecognizer(pinchGesture)
    
        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(transformViewGestureHandler(_:)))
        rotationGesture.delegate = self
        self.view.addGestureRecognizer(rotationGesture)
    
        transformEditingView = UIView(frame: self.view.bounds.insetBy(dx: 100, dy: 100))
        transformEditingView?.backgroundColor = UIColor.clear
    
        self.view.addSubview(transformEditingView!)
    
        transformEditingView?.layer.cornerRadius = 4.0
        transformEditingView?.layer.borderWidth = 4.0
        transformEditingView?.layer.borderColor = UIColor.red.cgColor
     }

// MARK: - Gestures for tansformEditingView

func transformUsingRecognizer(_ recognizer: UIGestureRecognizer, transform: CGAffineTransform) -> CGAffineTransform {
    
    if let rotateRecognizer = recognizer as? UIRotationGestureRecognizer {
        return transform.rotated(by: rotateRecognizer.rotation)
    }
    
    if let pinchRecognizer = recognizer as? UIPinchGestureRecognizer {
        let scale = pinchRecognizer.scale
        return transform.scaledBy(x: scale, y: scale)
    }
    
    if let panRecognizer = recognizer as? UIPanGestureRecognizer {
        let deltaX = panRecognizer.translation(in: self.view).x
        let deltaY = panRecognizer.translation(in: self.view).y
        
        return transform.translatedBy(x: deltaX, y: deltaY)
    }
    
    return transform
}

var initialTransform: CGAffineTransform?

var gestures = Set<UIGestureRecognizer>(minimumCapacity: 3)

@IBAction func transformViewGestureHandler(_ gesture: UIGestureRecognizer) {
    
    switch gesture.state {
        
    case .began:
        if gestures.count == 0 {
            initialTransform = transformEditingView.transform
        }
        gestures.insert(gesture)
        
    case .changed:
        if var initialTransform = initialTransform  {
            gestures.forEach({ (gesture) in
                initialTransform = transformUsingRecognizer(gesture, transform: initialTransform)
            })
            transformEditingView.transform = initialTransform
            
        }
        
    case .ended:
        gestures.remove(gesture)
        
    default:
        break
    }
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    
    return true
}
  }

   

编辑:我发现以下更改解决了问题,但不确定原因。

    let deltaX = panRecognizer.translation(in: transformEditingView).x
    let deltaY = panRecognizer.translation(in: transformEditingView).y

试一试 -- 似乎适用于同步平移/旋转/缩放:

class PinchPanRotateViewController: UIViewController, UIGestureRecognizerDelegate {
    
    let testView: UILabel = {
        let v = UILabel()
        v.text = "TEST"
        v.textAlignment = .center
        v.textColor = .yellow
        
        v.layer.cornerRadius = 4.0
        v.layer.borderWidth = 4.0
        v.layer.borderColor = UIColor.red.cgColor
        v.layer.masksToBounds = true

        //Enable multiple touch and user interaction
        v.isUserInteractionEnabled = true
        v.isMultipleTouchEnabled = true
        
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .blue
        
        view.addSubview(testView)
        testView.frame = CGRect(x: 0, y: 0, width: 240, height: 180)
        testView.center = view.center
        
        //add pan gesture
        let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        gestureRecognizer.delegate = self
        testView.addGestureRecognizer(gestureRecognizer)
        
        //add pinch gesture
        let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(handlePinch(_:)))
        pinchGesture.delegate = self
        testView.addGestureRecognizer(pinchGesture)
        
        //add rotate gesture.
        let rotate = UIRotationGestureRecognizer.init(target: self, action: #selector(handleRotate(_:)))
        rotate.delegate = self
        testView.addGestureRecognizer(rotate)
    }
    
    @objc func handlePan(_ pan: UIPanGestureRecognizer) {
        if pan.state == .began || pan.state == .changed {
            guard let v = pan.view else { return }
            let translation = pan.translation(in: self.view)
            v.center = CGPoint(x: v.center.x + translation.x, y: v.center.y + translation.y)
            pan.setTranslation(CGPoint.zero, in: self.view)
        }
    }
    
    @objc func handlePinch(_ pinch: UIPinchGestureRecognizer) {
        guard let v = pinch.view else { return }
        v.transform = v.transform.scaledBy(x: pinch.scale, y: pinch.scale)
        pinch.scale = 1
    }
    
    @objc func handleRotate(_ rotate: UIRotationGestureRecognizer) {
        guard let v = rotate.view else { return }
        v.transform = v.transform.rotated(by: rotate.rotation)
        rotate.rotation = 0
    }
    
    func gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
        return true
    }

}