Search code examples
iosswiftuiscrollviewuiimageviewzooming

Zooming an UIImageView that contains subviews


I have an UIImageView object in UIScrollView(to zoom). In addition, UIImageView also contains subviews. I am using following function to zoom in UIImageView.

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return self.imageView
}

It works perfectly fine for UIImageView.

The problem is when zooming these subviews, it also zooms these subviews the same way. Is there a way to disable zooming for these subviews?


Solution

  • There are many ways to achieve this. I would say the easiest one is to simply back-scale your views. This is what I used as a demo:

    class ViewController: UIViewController {
    
        @IBOutlet private var scrollView: UIScrollView?
        private var imageView: UIImageView?
        private var annotations: [UIView] = [UIView]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let imageView = UIImageView(image: UIImage(named: "background"))
            scrollView?.addSubview(imageView)
            scrollView?.contentSize = imageView.bounds.size
            scrollView?.maximumZoomScale = 5.0
            self.imageView = imageView
    
            scrollView?.delegate = self
    
            applyAnnotationView({
                let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
                view.backgroundColor = UIColor.red
                view.layer.cornerRadius = view.bounds.width*0.5
                return view
            }(), at: CGPoint(x: 100.0, y: 100.0))
    
            applyAnnotationView({
                let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
                view.backgroundColor = UIColor.green
                view.layer.cornerRadius = view.bounds.width*0.5
                return view
            }(), at: CGPoint(x: 200.0, y: 200.0))
        }
    
        func applyAnnotationView(_ view: UIView, at position: CGPoint) {
            view.center = position
            annotations.append(view)
            imageView?.addSubview(view)
        }
    
    }
    
    // MARK: - UIScrollViewDelegate
    
    extension ViewController: UIScrollViewDelegate {
    
        func scrollViewDidZoom(_ scrollView: UIScrollView) {
            annotations.forEach { item in
                item.transform = CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale)
            }
        }
    
        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return imageView
        }
    
    }
    

    Simply applying CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale) does all the work. It should be OK even when using constraints.