modeller
modeller

Reputation: 3850

Why UIScrollView's content is not centered?

I am embedding a UIImageView inside UIContentView to make it zoomable and panable (reference. The problem is that the image is not centered correctly. It looks like the entire image content is shifted out of top left corner: enter image description here

While the printed content Offset is near zero: content offset is: (0.0, -20.0)

Here is my implementation:

import UIKit

class ZoomableImageView: UIScrollView {

    private struct Constants {
        static let minimumZoomScale: CGFloat = 0.5;
        static let  maximumZoomScale: CGFloat = 6.0;
    }


    // public so that delegate can access
    public let imageView = UIImageView()

    // gw: must be called to complete a setting
    public func setImage(image: UIImage) {
        imageView.image = image
        imageView.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

        self.contentSize = image.size


        let scaleFitZoomScale: CGFloat = min(
        self.frame.width / image.size.width ,
        self.frame.height / image.size.height
        )


        // reset scale and offset on each resetting of image
        self.zoomScale = scaleFitZoomScale
    }


    // MARK - constructor
    init() {
        // gw: there is no super.init(), you have to use this constructor as hack
        super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) // gw: relies on autolayout constraint later

        minimumZoomScale = Constants.minimumZoomScale
        maximumZoomScale = Constants.maximumZoomScale

        addSubview(imageView)


    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }



}

ViewController:

class ViewController: UIViewController, UIScrollViewDelegate {


    let zoomableImageView  = ZoomableImageView()


    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(zoomableImageView)
        zoomableImageView.delegate = self

    }

    override func viewDidLayoutSubviews() {

        zoomableImageView.frame = view.frame
        let image = UIImage(imageLiteralResourceName: "kelly")
        zoomableImageView.setImage(image: image)

    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        // print("scale factor is: \(scrollView.zoomScale)")
        return zoomableImageView.imageView
    }

    func scrollViewDidZoom(_ scrollView: UIScrollView) {
         print("scale factor is: \(scrollView.zoomScale)")
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("content offset is: \(scrollView.contentOffset)")
    }



}

However, the centering of image works perfectly fine if I don't wrap the UIImageView and UIScrollView under the custom class:

class ViewController: UIViewController, UIScrollViewDelegate {


    let imageView: UIImageView = {
        let image = UIImage(imageLiteralResourceName: "kelly")
        let imageView = UIImageView(image: image)
        imageView.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
        return imageView
    } ()

    let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        return scrollView
    } ()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        view.addSubview(scrollView)
        scrollView.addSubview(imageView)


        scrollView.delegate = self
        self.scrollView.minimumZoomScale = 0.5;
        self.scrollView.maximumZoomScale = 6.0;

    }

    override func viewDidLayoutSubviews() {
        scrollView.frame = view.frame

        if let size = imageView.image?.size {
            scrollView.contentSize = size
        }



    }

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


}

Did I missed something in the first implementation?

Upvotes: 0

Views: 290

Answers (1)

DonMag
DonMag

Reputation: 77476

In your ZoomableImageView class, you are setting bounds when it should be frame

So change:

imageView.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) 

to

imageView.frame =  CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

Upvotes: 2

Related Questions