Having an image viewer within your app is a trivial feature; For one of my apps I needed one and found a tutorial on Ray Wenderlich website but it was not exactly what I wanted. You could zoom in and out the image but the image sticked to the top left corner of the screen, I wanted it to be centered. Also, is not it nicer for this simple UI to do everything in code? no dealing with storyboard for constraints and two elements makes maintaining the code easer in the future.
let scrollView = UIScrollView()
let imageView: UIImageView = {
let _imageView = UIImageView()
_imageView.translatesAutoresizingMaskIntoConstraints = false
return _imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
setupViews()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let image = UIImage(named: "image.jpg") {
scrollView.contentSize = image.size
imageView.image = image
let minZoom = min(self.view.bounds.size.width / image.size.width,
self.view.bounds.size.height / image.size.height)
self.scrollView.minimumZoomScale = minZoom
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
let vertical = (self.view.bounds.size.height - (image.size.height * minZoom)) / 2
self.scrollView.contentInset = UIEdgeInsets(top: vertical, left: 0, bottom: vertical, right: 0)
self.scrollView.setZoomScale(minZoom, animated: true)
}
}
}
func setupScrollView(){
scrollView.translatesAutoresizingMaskIntoConstraints = false
imageView.translatesAutoresizingMaskIntoConstraints = false
scrollView.delegate = self
view.addSubview(scrollView)
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
scrollView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
scrollView.minimumZoomScale = 0.2
}
func setupViews(){
scrollView.addSubview(imageView)
}
func centerContent() {
var top: CGFloat = 0
var left: CGFloat = 0
if scrollView.contentSize.width < scrollView.bounds.size.width {
left = (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5
}
if scrollView.contentSize.height < scrollView.bounds.size.height {
top = (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5
}
scrollView.contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left)
}
The last step is conforming to UIScrollViewDelegate
protocol:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
centerContent()
}
You can download the project from github.