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

时间:2017-06-10 14:33:27

标签: ios swift uigesturerecognizer uipangesturerecognizer

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

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

UIGestureRecognizerDelegate为此目的提供了一个可选功能shouldRecognizeSimultaneouslyWith。返回true只能避免一次只有一个效果:

// MARK: - UIGestureRecognizerDelegate
extension GestureController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

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

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

1 个答案:

答案 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
    }
}