同时使用多个UIGestureRecognizer,如Swift 3中的UIRotationGestureRecognizer和UIPanGestureRecognizer

在iOS上的现代用户界面中,在单个视图上实现多个UIGestureRecognizer通常很有用,以便为模拟现实世界的显示对象提供更真实的行为。

例如,您可能希望既可以在屏幕上拖动视图,也可以使用两个手指旋转它。

为此, UIGestureRecognizerDelegate提供了一个可选的函数shouldRecognizeSimultaneouslyWith 。 返回true避免一次只有一个有效的手势:

 // MARK: - UIGestureRecognizerDelegate extension GestureController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } } 

但是,当多个手势识别器处于活动状态时,尤其是UIRotationGestureRecognizer ,由于处理程序不断地相互覆盖,因此发现视图意外行为可能会令人沮丧。

如何实现多个手势识别器以提供流畅的行为?

同时实现多个手势识别器的关键是修改他们的CGAffineTransforms而不是覆盖它们。

Apple>文档>核心图形> CGAffineTransform :

请注意,您通常不需要直接创建仿射变换。 例如,如果只想绘制缩放或旋转的对象,则不必构造仿射变换。 操纵绘图的最直接方法 – 无论是通过移动,缩放还是旋转 – 分别调用函数translateBy(x:y :),scaleBy(x:y :)或rotate(by :)。 如果您想稍后重复使用,通常只应创建仿射变换。

此外,当检测到更改时,在应用翻译之后, 重置发送者的值是很重要的 ,这样翻译在每次检测到时都不会复合。

例如:

 @IBAction func rotateAction(_ sender: UIRotationGestureRecognizer) { guard let view = sender.view else { return } switch sender.state { case .changed: view.transform = view.transform.rotated(by: sender.rotation) sender.rotation = 0 default: break } } 

 @IBAction func panAction(_ sender: UIPanGestureRecognizer) { guard let view = sender.view else { return } switch sender.state { case .changed: let translationX = sender.translation(in: view).x let translationY = sender.translation(in: view).y view.transform = view.transform.translatedBy(x: translationX, y: translationY) sender.setTranslation(CGPoint.zero, in: view) default: break } }