Reputation: 1491
I'm having a problem with pinch zooming a UIImageView
which is set inside a UIScrollView
. The image zooms in response to the user's pinch inputs, but the image zooms and gets bigger until it takes up the entire screen rather than staying inside the bounds of my UIScrollView
. I have had a look at a heap of different SO questions, articles and YouTube videos to try and find the source of the problem but haven't been able to find anything.
The following SO questions seem to be loosely related but I still couldn't resolve my problem after looking at them:
My UIScrollView
is created in my storyboard and I used layout constraints created in the interface builder to anchor it in place. I set the scroll view's delegate to self in viewDidLoad()
(and have added UIScrollViewDelegate
to the top of my class). The UIImageView
is created programmatically. I declare the image view at the top of the class as below:
class VCImageViewer: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var lblImageTitle: UILabel!
@IBOutlet weak var btnBack: UIButton!
@IBOutlet weak var scrollView: UIScrollView!
var imageView:UIImageView = UIImageView() // <-- Image view
I then add the image view as a sub view of my UIScrollView
with the follow line of code, called during viewDidLoad()
:
self.scrollView.addSubview(self.imageView)
After adding the image view to the scroll view, I load an image into the image view. I fetch the image from a URL, and load it in using the following code. Again, this is called in viewDidLoad()
.
self.imageView.image = UIImage(data: data)
self.imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: (self.imageView.image?.size)!)
if self.imageView.image != nil {
self.lblError.isHidden = true
self.FormatImageViewerWithImage()
}
This confirms that the image has loaded correctly, hides a warning label I would display if it hadn't, and calls self.FormatImageViewerWithImage()
, which is below:
func FormatImageViewerWithImage() {
// Constraints
let constraintImageViewTop:NSLayoutConstraint = NSLayoutConstraint(item: self.imageView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.scrollView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let constraintImageViewBottom:NSLayoutConstraint = NSLayoutConstraint(item: self.imageView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.scrollView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let constraintImageViewLeft:NSLayoutConstraint = NSLayoutConstraint(item: self.imageView, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.scrollView, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0)
let constraintImageViewRight:NSLayoutConstraint = NSLayoutConstraint(item: self.imageView, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.scrollView, attribute: NSLayoutAttribute.right, multiplier: 1, constant: 0)
self.view.addConstraints([constraintImageViewTop, constraintImageViewBottom, constraintImageViewLeft, constraintImageViewRight])
self.scrollView.contentSize = self.imageView.image!.size
self.scrollView.clipsToBounds = false
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width
let scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
self.scrollView.minimumZoomScale = minScale
self.scrollView.maximumZoomScale = 1.0
self.scrollView.zoomScale = minScale
}
I have also implemented scrollViewDidZoom
with:
func scrollViewDidZoom(_ scrollView: UIScrollView) {
self.CentreScrollViewContents()
}
func CentreScrollViewContents() {
let boundsSize = self.scrollView.bounds.size
var contentsFrame = self.imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2
} else {
contentsFrame.origin.x = 0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2
} else {
contentsFrame.origin.y = 0
}
self.imageView.frame = contentsFrame
}
and viewForZooming
with:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imageView
}
I have seen previous questions (including some listed above) which suggested adding code to viewWillLayoutSubviews()
, but I have not had any success with that, so my viewWillLayoutSubviews()
is empty.
Can anyone see anything I am doing wrong?
Upvotes: 1
Views: 1230
Reputation: 2099
Please change this line:
self.scrollView.clipsToBounds = false
to this line:
self.scrollView.clipsToBounds = true
Hope this helps!
Upvotes: 1