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.
