0

I want to drag and zoom UIImageView inside UIView not in UIViewController (self.view) using swift 3.0.

Here I have declare mainView and imageView,

var lastScale: CGFloat = 0.0
@IBOutlet var mainView: UIView!
@IBOutlet var imageView: UIImageView!

I have set Pan and Pinch Gesture for zoom and drag imageview inside mainView

let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(ViewController.handlePinchGesture(_:)))
    imageView.isUserInteractionEnabled = true
    imageView.addGestureRecognizer(pinchGestureRecognizer)

let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ViewController.handlePanGesture(recognizer:)))
    imageView.addGestureRecognizer(panGestureRecognizer)

Function for pan and pinch gesture

func handlePinchGesture(_ gestureRecognizer: UIPinchGestureRecognizer) {
    if gestureRecognizer.state == .began {
        lastScale = gestureRecognizer.scale
    }

    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
        let currentScale: CGFloat = (gestureRecognizer.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: CGFloat = 1 - (lastScale - gestureRecognizer.scale)

        //newScale = min(newScale, kMaxScale / currentScale)
        newScale = max(newScale, kMinScale / currentScale)

        let transform = gestureRecognizer.view?.transform.scaledBy(x: newScale, y: newScale)
        gestureRecognizer.view?.transform = transform!

        lastScale = gestureRecognizer.scale
    }
}

func handlePanGesture(recognizer: UIPanGestureRecognizer) {
    let translation = recognizer.translation(in: mainView)
    var recognizerFrame = recognizer.view?.frame
    recognizerFrame?.origin.x += translation.x
    recognizerFrame?.origin.y += translation.y
    // Check if UIImageView is completely inside its superView
    if mainView.bounds.contains(recognizerFrame!) {
        recognizer.view?.frame = recognizerFrame!
    }
    else {
        // Check vertically
        if (recognizerFrame?.origin.y)! < mainView.bounds.origin.y {
            recognizerFrame?.origin.y = 0
        }
        else if (recognizerFrame?.origin.y)! + (recognizerFrame?.size.height)! > mainView.bounds.size.height {
            recognizerFrame?.origin.y = mainView.bounds.size.height - (recognizerFrame?.size.height)!
        }

        // Check horizantally
        if (recognizerFrame?.origin.x)! < mainView.bounds.origin.x {
            recognizerFrame?.origin.x = 0
        }
        else if (recognizerFrame?.origin.x)! + (recognizerFrame?.size.width)! > mainView.bounds.size.width {
            recognizerFrame?.origin.x = mainView.bounds.size.width - (recognizerFrame?.size.width)!
        }
    }

    // Reset translation so that on next pan recognition
    // we get correct translation value
    recognizer.setTranslation(CGPoint(x: CGFloat(0), y: CGFloat(0)), in: mainView)
}

When I run this code, And I'm zoom imageView it's go outside of mainView. So, How can I fixed?

Himanshu Patel
  • 1,015
  • 8
  • 26

1 Answers1

0

Whenever you scale your subview or move your subview, the frame value of subview needs to be changed. Because frame is a property of UIView, you can use KVO to observe it and set some rules for its changes like your way done for pan etc.

For KVO of frame, you can find better explanation from here

Community
  • 1
  • 1
brianLikeApple
  • 4,262
  • 1
  • 27
  • 46