I have an image view as a subview of a UIScrollView in order to enable zooming the image. It somewhat works but not well.
class LargeImageViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!
var selectedImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
if let image = selectedImage {
imageView.image = image
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateMinZoomScaleForSize(view.bounds.size)
}
func updateMinZoomScaleForSize(_ size: CGSize) {
let widthScale = size.width / imageView.bounds.width
let heightScale = size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
scrollView.minimumZoomScale = minScale
scrollView.zoomScale = minScale
}
@IBAction func doneTapped(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension LargeImageViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
updateConstraintsForSize(view.bounds.size)
}
func updateConstraintsForSize(_ size: CGSize) {
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
imageViewTopConstraint.constant = yOffset
imageViewBottomConstraint.constant = yOffset
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
imageViewLeadingConstraint.constant = xOffset
imageViewTrailingConstraint.constant = xOffset
view.layoutIfNeeded()
}
}
Any ideas?
I have now tried following the tutorial suggested and it behaves a little better, but the image is zoomed in and huge.
My constraints are still giving me issues even though I followed the tutorial.
Couple reasons your code is not working like the tutorial.
1 - You missed setting the scroll view delegate (unless you set it in Storyboard). If you did not set it in Storyboard:
override func viewDidLoad() {
super.viewDidLoad()
if let image = selectedImage {
imageView.image = image
}
// add this
scrollView.delegate = self
}
2 - It will still not be quite correct, because the tutorial sets the image in Storyboard, but you're setting it in viewDidLoad()
. To fix that:
// remove this
//override func viewWillLayoutSubviews() {
// super.viewWillLayoutSubviews()
// updateMinZoomScaleForSize(view.bounds.size)
//}
// add this
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateMinZoomScaleForSize(scrollView.bounds.size)
updateConstraintsForSize(scrollView.bounds.size)
}
3 - To get rid of the constraint errors in your Storyboard, give the image view Width and Height constraints (such as 100 each), and set them as Placeholders so they will not be used at run-time: