Using multiple UIGestureRecognizers simultaneously like UIRotationGestureRecognizer & UIPanGestureRecognizer in Swift 3

≯℡__Kan透↙ 提交于 2019-12-06 13:20:17

问题


In modern user interfaces on iOS, it is often useful to implement multiple UIGestureRecognizers on a single view, in order to provide more realistic behavior of displayed objects that model the real world.

For example, you might want to be able to both drag a view around the screen, but also use two fingers to rotate it.

The UIGestureRecognizerDelegate provides an optional function shouldRecognizeSimultaneouslyWith for this purpose. Returning true avoids only one gesture having effect at a time:

// MARK: - UIGestureRecognizerDelegate
extension GestureController: UIGestureRecognizerDelegate {

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

However, when multiple gesture recognisers are active, especially UIRotationGestureRecognizer it can be frustrating to find the view behaving unexpectedly as the handlers constantly override each other.

How can multiple gesture recognisers be implemented to provide smooth behavior?


回答1:


The key to implementing multiple gesture recognisers simultaneously is modifying their CGAffineTransforms rather than overwriting them.

Apple > Documentation > Core Graphics > CGAffineTransform:

Note that you do not typically need to create affine transforms directly. If you want only to draw an object that is scaled or rotated, for example, it is not necessary to construct an affine transform to do so. The most direct way to manipulate your drawing—whether by movement, scaling, or rotation—is to call the functions translateBy(x:y:) , scaleBy(x:y:) , or rotate(by:) , respectively. You should generally only create an affine transform if you want to reuse it later.

Furthermore, when changes are detected, after applying the translation, it is important to reset the value of the sender, so that the translations do not compound each time they are detected.

For example:

@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
    }
}

and

@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
    }
}


来源:https://stackoverflow.com/questions/44474496/using-multiple-uigesturerecognizers-simultaneously-like-uirotationgesturerecogni

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!