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