在iOS上的现代用户界面中,在单个视图上实现多个UIGestureRecognizers通常很有用,以便为模拟现实世界的显示对象提供更真实的行为。
例如,您可能希望既能在屏幕上拖动视图,又希望能够使用两根手指旋转视图。
UIGestureRecognizerDelegate
为此提供了一个可选功能shouldRecognizeSimultaneouslyWith
。返回true
可避免一次只对一个手势产生影响:
// MARK: - UIGestureRecognizerDelegate
extension GestureController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
但是,当多个手势识别器处于活动状态时,尤其是在UIRotationGestureRecognizer
发现视图行为异常时,由于处理程序不断相互覆盖,可能会令人沮丧。
如何实现多个手势识别器以提供流畅的行为?
同时实现多个手势识别器的关键是修改其CGAffineTransforms
而不是覆盖它们。
Apple> Documentation> Core Graphics> CGAffineTransform:
请注意,通常不需要直接创建仿射变换。例如,如果只想绘制缩放或旋转的对象,则无需构造仿射变换即可执行此操作。操作绘图的最直接方法(无论是通过移动、缩放还是旋转)是调用函数 translateBy(x:y:) , scaleBy(x:y:) 或 旋转(按:) 分别。通常,只有在以后要重用仿射变换时,才应创建仿射变换。
此外,当检测到更改时,在应用翻译后,重置发送方的值非常重要,这样每次检测到翻译时都不会复合。
例如:
@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
}
}