I'm trying to convert part 1 of the Ray Wenderlich UIScrollView Tutorial into Autolayout with universal devices. I currently have a UITableView
embedded in a Navigation Controller, connecting a UIViewController
of class ViewController
with a UIScrollView
(of no custom class). The Navigation Controller has an opaque navigation bar and no toolbar. The Attributes for the UIViewController
can be seen in the first image in the album below.
With just the four storyboard constraints (outlined below), my view looked like the second image in the album, with the scrollView
's frame size at an incorrect 600x536
. To fix this, I decided to add the constraints again at runtime, in viewDidLoad()
in ViewController.swift
. I now have 8 total constraints:
- 4 constraints on the storyboard:
scrollView.top
=topLayoutGuide.bottom
scrollView.bottom
=bottomLayoutGuide.top
scrollView.leading
=superView.leading
scrollView.trailing
=superView.trailing
- 4 contraints in
ViewController.swift
:scrollView.top
=topLayoutGuide
scrollView.bottom
=view.bottom
scrollView.leading
=view.leading
scrollView.trailing
=view.trailing
With these constraints, before zooming, my view now looks like the third album image, with scrollView
's frame size at a still incorrect 375x667
. After zooming, my view is correct, looking like the fourth album image, with scrollView
's frame size at a correct 375x603
. A few other notes:
self.topLayoutGuide.length = 0
. Shouldn't it be 64? 20 from the status bar and 44 from the navigation bar?- Removing the storyboard constraints leads to the same problem as not having programmatic constraints. Why do the storyboard constraints still need to be there?
- I have tried both pure and mixed approaches, neither of which have solved this problem.
- As well as disabling
Adjust Scroll View Insets
,Extend Edges Under Top Bars
, andExtend Edges Under Opaque Bars
in the storyboard (see first image), I am also disabling them in code, to no avail. - I can't use insets because the frame of the
UIScrollView
changes after zooming.
How can I get the UIScrollView
to be a constant, proper size?
Thank you.
class ViewController: UIViewController, UIScrollViewDelegate
@IBOutlet var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//Reset the layout
scrollView.needsUpdateConstraints()
scrollView.setNeedsLayout()
scrollView.layoutIfNeeded()
//Set storyboard settings just in case
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.extendedLayoutIncludesOpaqueBars = false
self.edgesForExtendedLayout = .None
self.automaticallyAdjustsScrollViewInsets = false
self.navigationController?.navigationBar.translucent = false
//Manually added constraints at runtime
var constraintTS = NSLayoutConstraint(item: scrollView, attribute: .Top, relatedBy: .Equal, toItem: topLayoutGuide, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintBS = NSLayoutConstraint(item: scrollView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintLS = NSLayoutConstraint(item: scrollView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0)
var constraintRS = NSLayoutConstraint(item: scrollView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0)
view.addConstraint(constraintTS)
view.addConstraint(constraintBS)
view.addConstraint(constraintLS)
view.addConstraint(constraintRS)
println(scrollView.frame.width)
println(scrollView.frame.height)
//Original Ray Wenderlich code
let image1 = UIImage(named: "photo1")!
imageView = UIImageView(image: image1)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image1.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image1.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
centerScrollViewContents()
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.height) / 2.0
println("boundsSize.height: \(boundsSize.height)")
println("boundsSize.width: \(boundsSize.width)")
println("contentsFrame.origin.y: \(contentsFrame.origin.y)")
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
override func viewWillLayoutSubviews() {
println(self.topLayoutGuide.length)
}