I have a UIViewController that has a UIScrollView. Within the latter view there is a UIImageView. I have implemented the UIImageView so that the user can zoom in/out. However, at the beginning I would like the user to see the entire UIImage before deciding to zoom in/out. Currently the UIImage is just automatically enlarged. A lot of the answers on stackOverflow suggested setting the UIImageView.contentMode to scaleAspectFit - i have done this but it has not worked.
class ViewImageViewController: UIViewController, UIScrollViewDelegate {
var imageToPresent: UIImage!
let scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let imageView: UIImageView = {
let imgView = UIImageView()
imgView.backgroundColor = UIColor.black
imgView.contentMode = .scaleAspectFit
imgView.isUserInteractionEnabled = true
imgView.translatesAutoresizingMaskIntoConstraints = false
return imgView
}()
override func viewDidLoad() {
super.viewDidLoad()
print("ViewImageViewController.viewDidLoad")
view.backgroundColor = UIColor.appGrayForLabels
setupViews()
scrollView.delegate = self
}
private func setupViews(){
view.addSubview(scrollView)
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 4.0
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
guard let img = imageToPresent else{return}
imageView.image = img
scrollView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
scrollView.isScrollEnabled = true
return imageView
}
You want to set the .minimumZoomScale
to the ratio between your image size and the scroll view size, and then set the .zoomScale
to that value to start with.
Here's your code, with a few modifications:
class ViewImageViewController: UIViewController, UIScrollViewDelegate {
var imageToPresent: UIImage!
let scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let imageView: UIImageView = {
let imgView = UIImageView()
imgView.backgroundColor = UIColor.black
imgView.contentMode = .scaleAspectFit
imgView.isUserInteractionEnabled = true
imgView.translatesAutoresizingMaskIntoConstraints = false
return imgView
}()
override func viewDidLoad() {
super.viewDidLoad()
print("ViewImageViewController.viewDidLoad")
if let img = UIImage(named: "background") {
imageToPresent = img
}
view.backgroundColor = .gray // UIColor.appGrayForLabels
setupViews()
scrollView.delegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.size.width / imageToPresent.size.width
let scaleHeight = scrollViewFrame.size.height / imageToPresent.size.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = minScale
}
private func setupViews(){
scrollView.isScrollEnabled = true
view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
guard let img = imageToPresent else{return}
imageView.image = img
scrollView.addSubview(imageView)
let g = scrollView.contentLayoutGuide
imageView.topAnchor.constraint(equalTo: g.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: g.bottomAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: g.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: g.trailingAnchor).isActive = true
imageView.widthAnchor.constraint(equalToConstant: imageToPresent.size.width).isActive = true
imageView.heightAnchor.constraint(equalToConstant: imageToPresent.size.height).isActive = true
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}