2017-01-11 64 views
-1

我有一个UIScrollViewUIImageView这样我就可以使用pinche放大图像视图中:如何将平移手势从UIScrollView转发到UIImageView?

extension CropperViewController : UIScrollViewDelegate { 

    func viewForZooming(in scrollView: UIScrollView) -> UIView? { 
     return self.imageView; 
    } 
} 

我现在也希望能够自由移动UIImageView所以我尝试添加一个UIPanGestureRecognizer to my UIImageView`:

self.imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))); 

func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { 
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { 
     let translation = gestureRecognizer.translation(in: self.view); 

     gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y); 
     gestureRecognizer.setTranslation(CGPoint.zero, in: self.view); 
    } 
} 

我现在有一个问题,就是根本没有触发pan touch事件,所以我想UIScrollView可能会捕获所有这些事件。因此,#2一些研究告诉我,以下内容添加到我的UIScrollView

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))); 
tapGestureRecognizer.numberOfTapsRequired = 1; 
tapGestureRecognizer.cancelsTouchesInView = false; 

self.scrollView.addGestureRecognizer(tapGestureRecognizer); 

,但实际上是什么也没有改变。缩放后,我可以缩放和移动图像,但我无法使用UIPanGestureRecognizer移动图像。我想使用UIScrollView来缩放,但我想使用UIPanGestureRecognizer移动UIImageView

我该怎么做?

编辑

也许可以禁用或更改UIScrollView的移动手势识别器和转发这些事件给UIImageView

回答

0

你需要给泛识别的委托,然后shouldRecogniseSimultaneouslyWith返回true ....

您可能还需要做同样的滚动视图的泛识别器,它可以作为一个属性。 。

另外,添加(使用addTarget(_,行动:)而不是创建自己的另一个目标/行动滚动视图的泛识别

+0

我不想'shouldRecogniseSimultaneouslyWith ....'。我希望ScrollView在UIImageView上处理缩放和PanGestureRecognizer来处理移动。 – Mulgard

0

试试这个:

scrollView.panGestureRecognizer.require(toFail: imagePanRecognizer)

如果您仍然有问题(如滚动感觉laggy)设置scrollView的delaysContentTouches为假

+0

似乎不起作用。 'handlePan'仍然没有得到任何事件。 – Mulgard

+0

然后尝试设置委托给你的UIPanGestureRecognizer,看看它的任何方法是否被调用。 – johnyu

+0

那是不可能的。该应用程序将终止一个异常,因为scrollviews uipangesturerecognizers委托neeeds为滚动视图本身。 – Mulgard

0

因为它似乎没有解决方案,我想出了不使用UIScrollView和impelementing UIPinchGestureRecognizerUIPanGestureRecognizerUIImageView通过自己:

import Foundation 
import UIKit 

/** 
* 
*/ 
protocol CropperCallback { 

    /** 
    * 
    */ 
    func croppingDone(image: UIImage); 

    /** 
    * 
    */ 
    func croppingCancelled(); 
} 

/** 
* 
*/ 
class CropperViewController : UIViewController { 
    /** 
    * 
    */ 
    @IBOutlet var imageView: UIImageView!; 
    /** 
    * 
    */ 
    var imageViewScaleCurrent: CGFloat! = 1.0; 
    var imageViewScaleMin: CGFloat! = 0.5; 
    var imageViewScaleMax: CGFloat! = 5.0; 
    /** 
    * 
    */ 
    @IBOutlet var cropAreaView: CropAreaView!; 
    /** 
    * 
    */ 
    @IBOutlet weak var cropAreaViewConstraintWidth: NSLayoutConstraint! 
    @IBOutlet weak var cropAreaViewConstraintHeight: NSLayoutConstraint! 
    /** 
    * 
    */ 
    @IBOutlet var btnCrop: UIButton!; 
    /** 
    * 
    */ 
    @IBOutlet var btnCancel: UIButton!; 

    /** 
    * 
    */ 
    var callback: CropperCallback! = nil; 
    /** 
    * 
    */ 
    var image: UIImage! = nil; 
    /** 
    * 
    */ 
    var imageOriginalWidth: CGFloat!; 
    var imageOriginalHeight: CGFloat!; 
    /** 
    * 
    */ 
    var cropWidth: CGFloat! = 287; 
    /** 
    * 
    */ 
    var cropHeight: CGFloat! = 292; 
    /** 
    * 
    */ 
    var cropHeightFix: CGFloat! = 1.0; 
    /** 
    * 
    */ 
    var cropArea: CGRect { 

     /** 
     * 
     */ 
     get { 
      let factor = self.imageView.image!.size.width/self.view.frame.width; 
      let scale = 1/self.imageViewScaleCurrent; 
      let x = (self.cropAreaView.frame.origin.x - self.imageView.frame.origin.x) * scale * factor; 
      let y = (self.cropAreaView.frame.origin.y - self.imageView.frame.origin.y) * scale * factor; 
      let width = self.cropAreaView.frame.size.width * scale * factor; 
      let height = self.cropAreaView.frame.size.height * scale * factor; 

      return CGRect(x: x, y: y, width: width, height: height); 
     } 
    } 

    /** 
    * 
    */ 
    static func storyboardInstance() -> CropperViewController? { 
     let storyboard = UIStoryboard(name: String(describing: NSStringFromClass(CropperViewController.classForCoder()).components(separatedBy: ".").last!), bundle: nil); 

     return storyboard.instantiateInitialViewController() as? CropperViewController; 
    } 

    /** 
    * 
    */ 
    override func viewDidLoad() { 
     super.viewDidLoad(); 

     self.imageView.image = self.image; 
     self.imageView.isUserInteractionEnabled = true; 
     self.imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))); 
     self.imageView.addGestureRecognizer(UIPinchGestureRecognizer(target: self, action: #selector(self.handlePinch(_:)))); 

     self.cropAreaViewConstraintWidth.constant = self.cropWidth; 
     self.cropAreaViewConstraintHeight.constant = self.cropHeight; 
     self.cropAreaView.layer.borderWidth = 1; 
     self.cropAreaView.layer.borderColor = UIColor(red: 173/255, green: 192/255, blue: 4/255, alpha: 1.0).cgColor; 

     self.btnCrop.addTarget(self, action: #selector(self.didTapCropButton), for: UIControlEvents.touchUpInside); 
     self.btnCancel.addTarget(self, action: #selector(self.didTapCancelButton), for: UIControlEvents.touchUpInside); 
    } 

    /** 
    * 
    */ 
    override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews(); 

     let imageOriginalRect = self.getRectOfImageInImageView(imageView: self.imageView); 

     self.imageOriginalWidth = imageOriginalRect.size.width; 
     self.imageOriginalHeight = imageOriginalRect.size.height; 
    } 

    /** 
    * 
    */ 
    func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { 
     if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { 
      let rect = self.getRectOfImageInImageView(imageView: self.imageView); 
      let xImage = rect.origin.x; 
      let yImage = rect.origin.y; 
      let widthImage = rect.size.width; 
      let heightImage = rect.size.height; 

      let xCropView = self.cropAreaView.frame.origin.x; 
      let yCropView = self.cropAreaView.frame.origin.y; 
      let widthCropView = self.cropAreaView.frame.size.width; 
      let heightCropView = self.cropAreaView.frame.size.height; 

      let translation = gestureRecognizer.translation(in: self.view); 

      var x: CGFloat; 
      var y: CGFloat; 

      if (translation.x > 0) { 
       if (!(xImage >= xCropView)) { 
        x = gestureRecognizer.view!.center.x + translation.x; 
       } else { 
        x = gestureRecognizer.view!.center.x; 
       } 
      } else if (translation.x < 0) { 
       if (!((xImage + widthImage) <= (xCropView + widthCropView))) { 
        x = gestureRecognizer.view!.center.x + translation.x; 
       } else { 
        x = gestureRecognizer.view!.center.x; 
       } 
      } else { 
       x = gestureRecognizer.view!.center.x; 
      } 

      if (translation.y > 0) { 
       if (!(yImage >= (yCropView - self.cropHeightFix))) { 
        y = gestureRecognizer.view!.center.y + translation.y; 
       } else { 
        y = gestureRecognizer.view!.center.y; 
       } 
      } else if (translation.y < 0) { 
       if (!((yImage + heightImage) <= (yCropView + heightCropView + self.cropHeightFix))) { 
        y = gestureRecognizer.view!.center.y + translation.y; 
       } else { 
        y = gestureRecognizer.view!.center.y; 
       } 
      } else { 
       y = gestureRecognizer.view!.center.y; 
      } 

      gestureRecognizer.view!.center = CGPoint(x: x, y: y); 
      gestureRecognizer.setTranslation(CGPoint.zero, in: self.view); 

      self.fixImageViewPosition(); 
     } 
    } 

    /** 
    * 
    */ 
    func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) { 
     if let view = gestureRecognizer.view { 
      let widthCropView = self.cropAreaView.frame.size.width; 
      let heightCropView = self.cropAreaView.frame.size.height; 

      if (((self.imageViewScaleCurrent * gestureRecognizer.scale * self.imageOriginalWidth) > widthCropView) 
       && ((self.imageViewScaleCurrent * gestureRecognizer.scale * self.imageOriginalHeight) > (heightCropView + (2 * self.cropHeightFix))) 
       && ((self.imageViewScaleCurrent * gestureRecognizer.scale) < self.imageViewScaleMax)) { 

       self.imageViewScaleCurrent = self.imageViewScaleCurrent * gestureRecognizer.scale; 

       view.transform = CGAffineTransform(scaleX: self.imageViewScaleCurrent, y: self.imageViewScaleCurrent); 
      } 

      gestureRecognizer.scale = 1.0; 

      self.fixImageViewPosition(); 
     } 
    } 

    /** 
    * 
    */ 
    func fixImageViewPosition() { 
     let rect = self.getRectOfImageInImageView(imageView: self.imageView); 
     let xImage = rect.origin.x; 
     let yImage = rect.origin.y; 
     let widthImage = rect.size.width; 
     let heightImage = rect.size.height; 

     let xCropView = self.cropAreaView.frame.origin.x; 
     let yCropView = self.cropAreaView.frame.origin.y; 
     let widthCropView = self.cropAreaView.frame.size.width; 
     let heightCropView = self.cropAreaView.frame.size.height; 

     if (xImage > xCropView) { 
      self.imageView.frame = CGRect(x: xCropView, y: self.imageView.frame.origin.y, width: widthImage, height: heightImage); 
     } 

     if ((xImage + widthImage) < (xCropView + widthCropView)) { 
      self.imageView.frame = CGRect(x: ((xCropView + widthCropView) - widthImage), y: self.imageView.frame.origin.y, width: widthImage, height: heightImage); 
     } 

     if (yImage > yCropView) { 
      self.imageView.frame = CGRect(x: self.imageView.frame.origin.x, y: (yCropView - self.cropHeightFix), width: widthImage, height: heightImage); 
     } 

     if ((yImage + heightImage) < (yCropView + heightCropView + self.cropHeightFix)) { 
      self.imageView.frame = CGRect(x: self.imageView.frame.origin.x, y: ((yCropView + heightCropView + self.cropHeightFix) - heightImage), width: widthImage, height: heightImage); 
     } 
    } 

    /** 
    * 
    */ 
    func getRectOfImageInImageView(imageView: UIImageView) -> CGRect { 
     let imageViewSize = imageView.frame.size; 
     let imageSize = imageView.image!.size; 

     let scaleW = imageViewSize.width/imageSize.width; 
     let scaleH = imageViewSize.height/imageSize.height; 
     let aspect = min(scaleW, scaleH); 

     var imageRect = CGRect(x: 0, y: 0, width: (imageSize.width * aspect), height: (imageSize.height * aspect)); 

     imageRect.origin.x = (imageViewSize.width - imageRect.size.width)/2; 
     imageRect.origin.y = (imageViewSize.height - imageRect.size.height)/2; 

     imageRect.origin.x += imageView.frame.origin.x; 
     imageRect.origin.y += imageView.frame.origin.y; 

     return imageRect; 
    } 

    /** 
    * 
    */ 
    func didTapCropButton(sender: AnyObject) { 
     let croppedCGImage = self.imageView.image?.cgImage?.cropping(to: self.cropArea); 
     let croppedImage = UIImage(cgImage: croppedCGImage!); 

     if (self.callback != nil) { 
      self.callback.croppingDone(image: croppedImage); 
     } 

     self.dismiss(animated: true, completion: nil); 
    } 

    /** 
    * 
    */ 
    func didTapCancelButton(sender: AnyObject) { 
     if (self.callback != nil) { 
      self.callback.croppingCancelled(); 
     } 

     self.dismiss(animated: true, completion: nil); 
    } 
} 

/** 
* 
*/ 
extension UIImageView { 

    /** 
    * 
    */ 
    func imageFrame() -> CGRect { 
     let imageViewSize = self.frame.size; 

     guard let imageSize = self.image?.size else { 
      return CGRect.zero; 
     } 

     let imageRatio = imageSize.width/imageSize.height; 
     let imageViewRatio = imageViewSize.width/imageViewSize.height; 

     if (imageRatio < imageViewRatio) { 
      let scaleFactor = imageViewSize.height/imageSize.height; 
      let width = imageSize.width * scaleFactor; 
      let topLeftX = (imageViewSize.width - width) * 0.5; 

      return CGRect(x: topLeftX, y: 0, width: width, height: imageViewSize.height); 
     } else { 
      let scaleFactor = imageViewSize.width/imageSize.width; 
      let height = imageSize.height * scaleFactor; 
      let topLeftY = (imageViewSize.height - height) * 0.5; 

      return CGRect(x: 0, y: topLeftY, width: imageViewSize.width, height: height); 
     } 
    } 
} 
相关问题