UIScrollView is unexpectedly initially zoomed in in UIViewControllerRepresentable

31 Views Asked by At

UIScrollView is initially zoomed in

I want to adapt an UIScrollView from UIKit to SwiftUI to give me the ability to zoom and pan in iOS 15.0. This is what I tried:

ContentView.swift:

NavigationView {
    UIZoomableScrollView()
        .navigationBarTitleDisplayMode(.inline)
        .navigationTitle("Buried Maze")
}
.navigationViewStyle(.stack)

UIZoomableScrollView.swift:

import SwiftUI

struct UIZoomableScrollView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> ZoomableScrollViewController {
        return ZoomableScrollViewController()
    }
    
    func updateUIViewController(_ uiViewController: ZoomableScrollViewController, context: Context) { }
}

ZoomableScrollViewController.swift:

import Foundation
import UIKit
import SnapKit
import SMScrollView

class ZoomableScrollViewController: UIViewController, UIScrollViewDelegate {

    fileprivate let zoomContainer: SMScrollView = {
        let scrollView = SMScrollView(frame: .zero)
        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 5.0
        scrollView.backgroundColor = .red

        scrollView.stickToBounds = true
        scrollView.fitOnSizeChange = false
        
        return scrollView
    }()
    
    
    fileprivate let mazeImageView: UIImageView = {
        let mazeImage: UIImage = UIImage(named: "buriedMaze")!
        let imageView = UIImageView(image: mazeImage)
        
        return imageView
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let imageSize = CGSize.sizeThatFits(containerSize: self.view.bounds.size, containedAR: 583.0/510.0)
        
        self.view.backgroundColor = .systemPink
        self.view.addSubview(self.zoomContainer)
        
        self.zoomContainer.delegate = self
                
        self.zoomContainer.snp.makeConstraints { make in
            make.center.equalTo(self.view)
            make.width.equalTo(imageSize.width)
            make.height.equalTo(imageSize.height)
        }
                
        self.zoomContainer.addSubview(mazeImageView)
        
        self.mazeImageView.snp.makeConstraints { make in
            make.top.left.right.bottom.equalTo(self.zoomContainer)
        }
        
        
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return self.mazeImageView
    }
}

In the context of the above code, SMScrollView comes from this github package, but it's not the source of the problem, since it's a subclass of UIScrollView and you can replace in the above code SCNScrollView with UIScrollView and the issue persists.

CGSize + sizeThatFits.swift:

import CoreGraphics

extension CGSize {
    static func sizeThatFits(containerSize: CGSize, containedAR: CGFloat) -> CGSize {
        if containedAR.isZero || containedAR.isNaN || containedAR.isInfinite {
            return .zero
        } else {
            let proposedHeightAtMaxWidth: CGFloat = containerSize.width/containedAR
            if proposedHeightAtMaxWidth > containerSize.height {
                return CGSize(width: containerSize.height*containedAR, height: containerSize.height)
            } else {
                return CGSize(width: containerSize.width, height: containerSize.width/containedAR)
            }
        }
    }
}

The image gets to its correct 0 zoom size as soon as I double tap the UIScrollView to reset zoom.

0

There are 0 best solutions below