在iOS上的现代用户界面中,在单个视图上实现多个UIGestureRecognizer通常很有用,以便为模拟现实世界的显示对象提供更真实的行为。
例如,您可能希望既可以在屏幕上拖动视图,也可以使用两个手指旋转它。
UIGestureRecognizerDelegate
为此目的提供了一个可选功能shouldRecognizeSimultaneouslyWith
。返回true
只能避免一次只有一个效果:
// MARK: - UIGestureRecognizerDelegate
extension GestureController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
但是,当多个手势识别器处于活动状态时,尤其是UIRotationGestureRecognizer
,由于处理程序不断地互相覆盖,因此发现视图意外行为可能会令人沮丧。
如何实施多个手势识别器以提供流畅的行为?
答案 0 :(得分:3)
同时实施多个手势识别器的关键是修改他们的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
}
}