UIImageView pinch zoom swift

一曲冷凌霜 提交于 2019-11-27 00:17:51
Parth Changela

UIImageView pinch zoom with UIScrollView || image zooming ios in swift 3 and Xcode 8 letter Youtube video URL

set uiscrollview Delegate in storyboard

 class PhotoDetailViewController: UIViewController, UIScrollViewDelegate {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var imgPhoto: UIImageView!

    override func viewDidLoad() {

        super.viewDidLoad()

        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 6.0        
        // scrollView.delegate = self - it is set on the storyboard.
    }  

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {

        return imgPhoto
    }
RandomBytes

I decided to add the imageView to a UIScrollView. It allows the user to zoom and pan over. Here is the code I used.

in order to set max/min zoom I used :

    scrollImg.minimumZoomScale = 1.0
    scrollImg.maximumZoomScale = 10.0

here is the rest of the code.

    var vWidth = self.view.frame.width
    var vHeight = self.view.frame.height

    var scrollImg: UIScrollView = UIScrollView()
    scrollImg.delegate = self
    scrollImg.frame = CGRectMake(0, 0, vWidth!, vHeight!)
    scrollImg.backgroundColor = UIColor(red: 90, green: 90, blue: 90, alpha: 0.90)
    scrollImg.alwaysBounceVertical = false
    scrollImg.alwaysBounceHorizontal = false
    scrollImg.showsVerticalScrollIndicator = true
    scrollImg.flashScrollIndicators()

    scrollImg.minimumZoomScale = 1.0
    scrollImg.maximumZoomScale = 10.0

    defaultView!.addSubview(scrollImg)

    imageView!.layer.cornerRadius = 11.0
    imageView!.clipsToBounds = false
    scrollImg.addSubview(imageView!)

I also had to add this as well

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

Swift 3 & above function prototype

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

The option for swift 4

class ViewController: UIViewController, UIScrollViewDelegate {

@IBOutlet weak var scrolView: UIScrollView!
@IBOutlet weak var imgPhoto: UIImageView!

  override func viewDidLoad() {
    super.viewDidLoad()
    scrolView.delegate = self
    scrolView.minimumZoomScale = 1.0
    scrolView.maximumZoomScale = 10.0
  }

  func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imgPhoto
  }
}

In my view, the problem is your determination of currentScale. It always equals 1, because you change the scale of your imageView. You should assign your currentScale as follows:

let currentScale = self.imageView?.frame.size.width / self.imageView?.bounds.size.width  

You can use ImageScrollView open source, a zoomable and scrollable image view. http://github.com/huynguyencong/ImageScrollView

Like this opensource, add ImageView to ScrollView

open class ImageScrollView: UIScrollView {
   var zoomView: UIImageView? = nil
}

extension ImageScrollView: UIScrollViewDelegate{

    public func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return zoomView
    }

    public func scrollViewDidZoom(_ scrollView: UIScrollView) {
        adjustFrameToCenter()
    }
}

Swift 3 solution

By default UIImageView's userInteration is disabled. Enable it before adding any gestures in UIImageView.

imgView.isUserInteractionEnabled = true

The scale factor relative to the points of the two touches in screen coordinates

var lastScale:CGFloat!
func zoom(gesture:UIPinchGestureRecognizer) {
    if(gesture.state == .began) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = gesture.scale
    }
    if (gesture.state == .began || gesture.state == .changed) {
    let currentScale = gesture.view!.layer.value(forKeyPath:"transform.scale")! as! CGFloat
    // Constants to adjust the max/min values of zoom
    let kMaxScale:CGFloat = 2.0
    let kMinScale:CGFloat = 1.0
    var newScale = 1 -  (lastScale - gesture.scale)
    newScale = min(newScale, kMaxScale / currentScale)
    newScale = max(newScale, kMinScale / currentScale)
    let transform = (gesture.view?.transform)!.scaledBy(x: newScale, y: newScale);
    gesture.view?.transform = transform
    lastScale = gesture.scale  // Store the previous scale factor for the next pinch gesture call
  }
}

Swift 3 solution

This is the code I used. I added imageView to scrollView as a subview.

class ZoomViewController: UIViewController,UIScrollViewDelegate {

@IBOutlet weak var scrollView:UIScrollView!
@IBOutlet weak var imageView:UIImageView!

override func viewDidLoad() {

        super.viewDidLoad()
        scrollView.delegate = self

        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 10.0//maximum zoom scale you want
        scrollView.zoomScale = 1.0

}

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

I think the biggest problem is at the end of your func, you have sender.scale = 1. If you remove that line of code, your image shouldn't just bounce back each time.

I posted an answer here for zoom functionality with both pinch and double tap in Swift 3. Works perfectly.

This is an old question but I don't see any answers that explain what is wrong with the original code.

This line:

let currentScale = self.view.frame.size.width / self.view.bounds.size.width

Is working on the main view rather than the imageView so the scale calculation is always ~1

This simple change makes it behave as expected

let currentScale = sender.view!.frame.size.width / sender.view!.bounds.size.width

by changing self to sender (and forcing view to unwrap) the scale calculation works as expected.

I ended up here, probably searching the wrong way.

I was after having my imageView in contentMode = .centre. But I was judging it too zoomed in and I was searching a way to zoom it out. Here's how:

    self.imageView.contentScaleFactor = 3

1 is as if you were doing anything. More that 1 zooms out... 3 works for me but you need to test it out.

Using Swift 5.0, here is how it works for me:

let myImageView = UIImageView(image: myImage)
myImageView.isUserInteractionEnabled = true
let pinchMethod = UIPinchGestureRecognizer(target: self, action: #selector(pinchImage(sender:)))
myImageView.addGestureRecognizer(pinchMethod)

@objc func pinchImage(sender: UIPinchMethodRecognizer) {
  guard let sender.view != nil else { return }

if let scale = (sender.view?.transform.scaledBy(x: sender.scale, y: sender.scale)) {
  guard scale.a > 1.0 else { return }
  guard scale.d > 1.0 else { return }
  sender.view?.transform = scale
  sender.scale = 1.0
 }
}

You can use scale.a, scale.b, scale.c, scale.d, scale.tx and scale.ty to set your scale limits.

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