UIPinchGestureRecognizer 在 UIRotationGestureRecognizer 之后不起作用

Posted

技术标签:

【中文标题】UIPinchGestureRecognizer 在 UIRotationGestureRecognizer 之后不起作用【英文标题】:UIPinchGestureRecognizer is not working after UIRotationGestureRecognizer 【发布时间】:2018-02-06 20:39:44 【问题描述】:

我在 UIView 上有 2 个手势识别器(旋转和捏合)。他们独立运作良好。如果我在捏后旋转,仍然可以正常工作。但是,如果我在旋转后捏捏,捏就不起作用。

捏:工作。 旋转:工作。 (旋转 -> 捏):不工作。 (捏合 -> 旋转):工作。 (捏合 -> 旋转 -> 捏合):不工作。

这是我的代码:

//gestures

  lazy var zoomGesture: UIPinchGestureRecognizer = 
    let zoom = UIPinchGestureRecognizer.init(target: self, action: #selector(handleZoom(_:)))
    zoom.delegate = self
    activeLayer.addGestureRecognizer(zoom)
    return zoom
  ()

  lazy var rotationGesture: UIRotationGestureRecognizer = 
    let rotation = UIRotationGestureRecognizer.init(target: self, action: #selector(handleRotation(_:)))
    rotation.delegate = self
    activeLayer.addGestureRecognizer(rotation)
    return rotation
  ()

//handlers

  @objc func handleZoom(_ gesture: UIPinchGestureRecognizer) 
    if gesture.state == .began 
      if activeLayer.initialTransform == nil 
        activeLayer.initialTransform = activeLayer.transform
      
     else if gesture.state == .changed 
      let scale = gesture.scale
      activeLayer.transform = activeLayer.initialTransform!.concatenating(CGAffineTransform.init(scaleX: scale, y: scale))
     else 
      activeLayer.initialTransform = nil
    
  

  @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) 
    if gesture.state == .began 
      if activeLayer.initialTransform == nil 
        activeLayer.initialTransform = activeLayer.transform
      
     else if gesture.state == .changed 
      let rotation = gesture.rotation
      activeLayer.transform = activeLayer.initialTransform!.concatenating(CGAffineTransform.init(rotationAngle: rotation))
     else 
      activeLayer.initialTransform = nil
    
  

  // delegate method

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

我做错了什么或错过了什么?谢谢。

【问题讨论】:

查看this question,似乎是一个类似的问题。 运气不好我已经查过了。 你是如何利用这个 activeLayer 的? @iosTeam,没什么大不了的。它是一个 UIView 子类,只有一个名为 initialTransform 的变量来保存手势开始时的变换信息。 【参考方案1】:

根据您的要求,这里有可行的解决方案。

斯威夫特 4

     //
     //  ViewController.swift
     //  GestureRecognizerQuestions
     //
     //  Created by Test User.
     //  Copyright © . All rights reserved.
     //

     import UIKit

     class ViewController: UIViewController , UIGestureRecognizerDelegate 

        var activeView : UIView!
        var initialTransform : CGAffineTransform?

        override func viewDidLoad() 
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            activeView = UIView(frame: self.view.frame)
            activeView.backgroundColor = UIColor.red
            self.view.addSubview(activeView)

            let rotation = UIRotationGestureRecognizer(target: self , action: #selector(handleRotation(_:)))
            rotation.delegate = self
            activeView.addGestureRecognizer(rotation)

            let zoomGesture = UIPinchGestureRecognizer(target: self , action: #selector(handleZoom(_:)))
            zoomGesture.delegate = self
            activeView.addGestureRecognizer(zoomGesture)


        

        //handlers

        @objc func handleZoom(_ gesture: UIPinchGestureRecognizer) 
            if gesture.state == .began 
                if self.initialTransform == nil 
                    self.initialTransform = activeView.transform
                
             else if gesture.state == .changed 
                let scale = gesture.scale
                activeView.transform = self.initialTransform!.concatenating(CGAffineTransform(scaleX: scale, y: scale))
              else if gesture.state == .ended 
                self.initialTransform = nil
            
        

        @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) 
            if gesture.state == .began 
                if self.initialTransform == nil 
                    self.initialTransform = activeView.transform
                
             else if gesture.state == .changed 
                let rotation = gesture.rotation
                activeView.transform = self.initialTransform!.concatenating(CGAffineTransform(rotationAngle: rotation))
             else if gesture.state == .ended 
                self.initialTransform = nil
            
        

        // delegate method
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
            return true
        
     

【讨论】:

嘿@Arda Oğul Üçpınar 你觉得我的解决方案对你有帮助吗?【参考方案2】:

好的。我了解到使用initialTransform 保持开始转换状态是一件愚蠢的事情。因为每次手势开始时,它都会改变initialTransform,这会导致一些意想不到的行为。

相反,我每次在应用到真正的视图转换后都会重置手势的scalerotation

代码如下:

  // .... gesture implementations etc ....

  @objc func handleZoom(_ gesture: UIPinchGestureRecognizer) 
    guard let activeLayer = activeLayer else 
      return
    
    let scale = gesture.scale

    // apply scale
    activeLayer.transform = activeLayer.transform.scaledBy(x: scale, y: scale)

    // reset scale to the default value 
    gesture.scale = 1
  

  @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) 
    guard let activeLayer = activeLayer else 
      return
    

    let rotation = gesture.rotation

    // apply rotation
    activeLayer.transform = activeLayer.transform.rotated(by: rotation)

    // reset rotation to the default value.
    gesture.rotation = 0
  

【讨论】:

以上是关于UIPinchGestureRecognizer 在 UIRotationGestureRecognizer 之后不起作用的主要内容,如果未能解决你的问题,请参考以下文章

UIPinchGestureRecognizer 与 UILongTapGestureRecognizer 的使用没有问题

使用 UIPinchGestureRecognizer 调整 UIView 的大小

UIPinchGestureRecognizer。放大手指的位置,而不仅仅是中心[重复]

UIPinchGestureRecognizer 向内捏“慢”

Swift - UIPageViewController中的UIPinchGestureRecognizer

当图像放大太大时,UIPinchGestureRecognizer 表现得很有趣