同时使用多个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 } }