Group Group Group Group Group Group Group Group Group

raywenderlich.com Forums

UIScrollView Tutorial: Getting Started

In this UIScrollView tutorial you'll learn how to zoom large images, center content while zooming, page content, and use Auto Layout with UIScrollView.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/560-uiscrollview-tutorial-getting-started

I thought iOS 11 introduced a simpler way to keep the content of a scrollview centered when zooming, as discussed in the WWDC 2017 sessions. It involves setting
imageView.centerXAnchor.constraints(equalTo: scrollView.contentLayoutGuide.centerXAnchor)
imageView.centerYAnchor.constraints(equalTo: scrollView.contentLayoutGuide.centerYAnchor)

Why did you keep the old method around in your updated tutorial ? Or am I missing something ?

MT

Sadly after adding the following lines…

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    updateMinZoomScaleForSize(view.bounds.size)
}

…and running the application the scrollView’s zoomScale property is not getting updated (it’s set to 1.0, by default I think) and the picture looks exactly the same way as in the previous step. I tried moving the call to updateMinZoomScaleForSize() method to viewDidAppear() without success, the zoomScale is still 1.0.

Pardon, mea culpa - I did not set the delegate for the scrollView, all is well now.

Hi frankdrebin123,

I tested the code you posted and it doesn’t work well with a scrollview (unless I’m missing something). Scrollview’s content size (width/height) is determined by the constraints of its contents to itself. The imageView must be constrained to the top/bottom/left/right of the scrollview. Constraining the centers doesn’t give the scrollview’s content an actual size.

I’ve watched the WWDC 2017 sessions dealing with layout. Which one were you referring to?

Thanks,
Owen

This is one of the possible solutions using scrollView.contentLayoutGuide

UIScrollView-AutoLayout

I was thinking of a solution similar but not sure that the extra UIView & code are worth the squeeze.

Session 201 look at the 24:51 (min:sec) mark.

Hi frankdrebin123,
Thanks for forwarding the session info. Somehow I missed this section.
I’ll look into putting together a clean solution that uses the center anchors and apply it to the tutorial.

Thanks,
Owen

Yes please! center anchors would be great because the current solution actually only works the first time the keyboard comes up and is dismissed (and maybe the Xcode Beta is buggy as sometimes not even then) but if you tap again to the text field after the keyboard is dismissed, the keyboard will show up but the view won’t move up. I printed the values to check what’s going on and somehow keyboardFrame.height has a value of 0 (and thus adjustmentHeight = 20) after the first dismiss of the keyboard.

Also, the tutorial says to add a Show Detail segue at the end which makes it impossible to go back to the previous View and leaves no choice but to end the app. The final project has a Show segue instead though, but then how can you hide the top menu like in the Photos app to have a full-screen view?

In any case, great tutorial!
Thanks!

Hi!
I used your code to scroll when the keyboard appears. I use swift 4. But when I use your code the contentInset is set but the view does not scroll automatically. Any Idea?
Thanks

Hi xilinx64,
I’m not sure what you mean by ‘not scroll automatically’.
I just tested with the final project and even with keyboard up on simulator, I can scroll side to side.
Give me a step by step and maybe I can help :slight_smile:

Owen

Hi. It doesn’t work well in iOS 11. Any suggestions?

Hi, how about setting the Origin Point UIScrollView’s bounds to the center of the screen and then set the image view’s center to CGPoint.zero?

Maybe we could first set the contentSize to zero, then set contentInset to add extra space, and then scroll the (0,0) to the center so that the origin point of the bounds of UIScrollView will be on the center of screen. Next we add imageView, set a frame to imageView and set imageView’s center to zero so that it is centered on screen?

Maybe you could go one step further and make a custom UIScrollView that automatically does the centering of imageView?

Hi, This is a very nice tutorial to understand concepts of scrollview. I implemented it my project. But I am facing a problem where I have nearly 4 textfields below each other. This code is moving the scroll more at the bottom if I go on clicking each text field. Any idea how to resolve this issue?

@owenb Do you have any feedback on this one? Thank you - much appreciated! :]

Please explain what issues you are having.
Thanks

Once change that is needed to the existing tutorial code is to replace UIKeyboardFrameBeginUserInfoKey with UIKeyboardFrameEndUserInfoKey. This fixes the issue of the scrollview not moving up properly after showing the keyboard the second time.
This will probably also fix your issue of multiple textfields not showing at the bottom.

I just updated the tutorial with this fix.

The site won’t let me post more than one link, so you will have to fix those manually to view them. My apologies.

There are issues when the images are too small. They do not get centered properly.

Take the following screenshot for example:

It looks fine at first, until you rotate it (put the link together manually):

https:/ /i .imgur. com/QMNumR7.png

On some devices, they look alright. Consider the following screenshot on both iPad and iPhone 7 Plus:

They look good when in portrait:

iPad: https://i.i mgur. com/buUh2FC.png
iPhone: https:/ /i.im gur. com/yYwQOYx.jpg

And look what happens on the iPad when you rotate. It goes to the left whereas it stays properly centered on iPhone:

iPad: https :// i. im gur. co m/aggcckX.png
iPhone: https:/ /i.im gur. co m/TfDpYCO.jpg

And that’s not the worst that can happen, sometimes, this happens on both iPad and iPhone:

https:/ /i.im gur. com/4Wl9tB U.png

What’s worse is that sometimes rotating the device and back fixes it. Not all the time.

I have tried to fix this by playing with the constraints. Unfortunately I can’t say I’ve had much luck. My only guess is this happens when both width and height dimensions are smaller than the screen.

Any clues on solving this? My web browser displays images for various sources, I can’t guarantee they will always be the same size.

So far I have been able to understand that rotating on iPad won’t call traitCollectionDidChange. It’s a bit of progress…

EDIT:

Alright, I was able to solve it on iPad by adding this:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { (context) in
        self.updateConstraintsForSize(self.view.bounds.size)
    })
}

There is still the fact that small images occasionally show misplaced when the view loads, but I’m sure I will get it eventually.