Reputation: 9361
I want to allow the user to side pan an image. The image should be scaled to the height of the device and the user is supposed to only be able to scroll left and right. The users is not supposed to be able to zoom.
I have a UIViewController
, to which I add a custom subclass ImageScrollView
.
This is supposed to display an image in full height, but instead the image is basically displayed un-zoomed. Even though the zoomScale gets calculated correctly, but does not have an effect.
What am I doing wrong?
Thanks
override func viewDidLoad() {
super.viewDidLoad()
let i = UIImage(named: "test.jpg")
let iSV = ImageScrollView(image: i)
self.view.addSubview(iSV)
iSV.fillSuperview()
}
class ImageScrollView: UIScrollView {
let image: UIImage
let imageView = UIImageView()
init(image img: UIImage) {
image = img
imageView.image = image
super.init(frame: .zero)
self.addSubview(imageView)
imageView.fillSuperview()
self.contentSize = image.size
self.showsHorizontalScrollIndicator = false
self.showsVerticalScrollIndicator = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.zoomScale = getZoomScale()
}
func getZoomScale() -> CGFloat{
let boundSize = self.frame.size
let yScale = boundSize.height / image.size.height
return yScale
}
}
And just for the case it has to do with auto-layout I included the fillSuperview
extension.
extension UIView {
public func fillSuperview() {
translatesAutoresizingMaskIntoConstraints = false
if let superview = superview {
topAnchor.constraint(equalTo: superview.topAnchor, constant: 0).isActive = true
leftAnchor.constraint(equalTo: superview.leftAnchor, constant: 0).isActive = true
bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0).isActive = true
rightAnchor.constraint(equalTo: superview.rightAnchor, constant: 0).isActive = true
}
}
}
Upvotes: 0
Views: 743
Reputation: 154711
Since you don't want the image to zoom, I recommend you don't even bother with the zoom controls. A UIImageView
knows how to scale its content.
I recommend you do it like this:
image.size.width / image.size.height
..scaleToFill
.To allow you to change the image, keep an aspectRatio
property that retains the aspect ratio constraint set in step 2. Set aspectRatio.isActive = false
, and then create and activate a new constraint for the new image.
Also, if you might ever have images that aren't wide enough to fill the scrollView horizontally when scaled to fit vertically, consider these changes:
max(image.size.width / image.size.height, scrollView.bounds.width / scrollView.bounds.height)
..scaleAspectFit
.Then, when you have a narrow image, the imageView will fill the scrollView, but the .scaleAspectFit
will show the entire image centered in the scrollView. This will still work correctly for wide images because the multiplier will match the image aspect ratio and .scaleAspectFit
will fill the entire imageView.
Upvotes: 1
Reputation: 16190
You forgot to implement scrollview delegate. And set min & max zoom level for scrollview.
var iSV: ImageScrollView?
let i = UIImage(named: "noWiFi")!
iSV = ImageScrollView(image: i)
if let iSV = iSV {
self.view.addSubview(iSV)
iSV.fillSuperview()
iSV.delegate = self
}
override func viewDidLayoutSubviews() {
if let iSV = iSV {
let scale = iSV.getZoomScale()
iSV.minimumZoomScale = scale
iSV.maximumZoomScale = scale
}
}
extension ViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return iSV?.imageView
}
}
Note: I just did rough. It may not fulfil your complete requirement
Upvotes: 1