2017-01-11 2 views
-1

У меня есть UIScrollView и внутри UIImageView, так что я могу 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); 
    } 
} 

У меня возникла проблема в том, что никакого события касания касания не было уволено вообще, поэтому я подумал, что UIScrollView ловит все эти события. Таким образом, некоторые исследования Stackoverflow сказал мне, чтобы добавить следующее к моей UIScrollView:

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

self.scrollView.addGestureRecognizer(tapGestureRecognizer); 

, но на самом деле это ничего не изменило. Я могу масштабировать и перемещать изображение после масштабирования, но я не могу перемещать изображение, используя UIPanGestureRecognizer. Я хочу использовать UIScrollView, чтобы иметь возможность масштабирования, но я хочу использовать UIPanGestureRecognizer для перемещения UIImageView.

Как я могу это сделать?

EDIT

Может быть, это можно отключить или изменить панорамирование жест распознаватель из UIScrollView и направить эти события в UIImageView?

ответ

0

Вы должны дать сковороду распознаватель делегата, а затем вернуться верно для shouldRecogniseSimultaneouslyWith ....

Вам также может понадобиться, чтобы сделать то же самое с панорамированием распознаватель отображения вида скроллинга, который доступен в качестве свойства. .

В качестве альтернативы, добавьте еще одну цель/действие для панорамирования распознаватель отображения вида скроллинга (с помощью addTarget (_, действие :) вместо создания собственного

+0

Я не хочу 'shouldRecogniseSimultaneouslyWith ....'. Я хочу, чтобы ScrollView обрабатывал масштабирование и PanGestureRecognizer в UIImageView для обработки перемещения. – Mulgard

0

Попробуйте это:

scrollView.panGestureRecognizer.require(toFail: imagePanRecognizer)

Если вы все еще возникают проблемы (например, ощущение прокрутки laggy) установлено значение scrollView delaysContentTouches на false

+0

Кажется не работает. 'HandlePan' по-прежнему не получает никакого события. – Mulgard

+0

Затем попробуйте установить делегат в свой UIPanGestureRecognizer и посмотреть, вызван ли какой-либо из его методов. – johnyu

+0

эта невозможно. приложение завершится с исключением, потому что делегат scipviews uipangesturerecognizers представляет собой сам scrollview. – Mulgard

0

Поскольку кажется, что нет решения для этого, я пришел к выводу, что не использовал UIScrollView и impelementing UIPinchGestureRecognizer и UIPanGestureRecognizer для моего UIImageView сам:

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); 
     } 
    } 
} 
Смежные вопросы