Uiscrollview top-left bottom-right scroll direction swift năm 2024

Update note: Ron Kliffer updated this tutorial for Xcode 11, Swift 5 and iOS 13. Ray Wenderlich wrote the original.

UIScrollView is one of the most versatile and useful controls in iOS. It’s the basis for the very popular UITableView and it’s a great way to present content that’s larger than a single screen.

In this UIScrollView tutorial, you’ll create an app similar to the default iOS Photos app and learn all about UIScrollView. You’ll learn how to:

  • Use UIScrollView to zoom and view a very large image.
  • Keep UIScrollView‘s content centered while zooming.
  • Use UIScrollView for vertical scrolling with Auto Layout.
  • Prevent the keyboard from hiding text input components.
  • Use extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView  
    
    } } 2 to allow scrolling through multiple pages of content.

This tutorial assumes you understand how to use Interface Builder to add objects and connect outlets between your code and storyboard scenes. If you’re not familiar with Interface Builder or storyboards, work through our storyboards tutorial before starting this one.

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the starter project, then open it in Xcode. Build and run using an iPhone 8 simulator to see what you’re starting with. Continue using the iPhone 8 simulator for the rest of the tutorial.

Uiscrollview top-left bottom-right scroll direction swift năm 2024

You’ll see that you have several photos available in your project. You can select a photo to see it full-sized, but sadly, the device’s limited size prevents you from seeing the whole photo.

What you really want is to fit the image to the device’s screen by default and zoom to see details, just like the Photos app does.

Can you fix it? Yes, you can!

Scrolling and Zooming a Large Image

To kick off this UIScrollView tutorial, you’ll set up a scroll view that lets the user pan and zoom an image.

Open Main.storyboard and drag a Scroll view from the Object Library onto the document outline, right below View on the Zoomed Photo View Controller scene. Then, move Image View inside your newly-added Scroll View. Your document outline should now look like this:

Uiscrollview top-left bottom-right scroll direction swift năm 2024

See that red arrow? Xcode is complaining that your Auto Layout rules are wrong.

To fix them, select Scroll View and click the Pin button at the bottom of the storyboard window. Add four new constraints: top, bottom, leading and trailing. Set each constraint’s constant to 0 and uncheck Constrain to margins. The result should look like this:

Uiscrollview top-left bottom-right scroll direction swift năm 2024

Now, select Image View and add the same four constraints on it. Make sure to pin the constraints to the Scroll View and not the Frame Layout Guide, like this:

Uiscrollview top-left bottom-right scroll direction swift năm 2024

Build and run.

Uiscrollview top-left bottom-right scroll direction swift năm 2024

Thanks to the scroll view, you can now swipe to see the full-size image! But what if you want to zoom in and out? Or what if you want to see the picture scaled to fit the device’s screen?

You’ll need to write code for those cases!

Panning and Zooming Your Image

Open ZoomedPhotoViewController.swift and add the following outlets inside the class declaration:

@IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint! @IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint! @IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint! @IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint! Back in Main.storyboard, set the

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 4 outlet to Scroll View and set the Scroll View’s

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 5 to Zoomed Photo View Controller. Also, connect the new constraint outlets to the appropriate constraints in the document outline, like this:

Uiscrollview top-left bottom-right scroll direction swift năm 2024

Back in ZoomedPhotoViewController.swift, add the following to the end of the file:

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } This makes

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 6 conform to

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 7 and implements

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 8. The scroll view calls this method to determine which of its subviews to scale when the user pinches the image. Here, you tell it to scale

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 9.

Setting the Zoom Scale

Next, add the following inside the class, right after

func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 0:

func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } This method calculates the zoom scale for the scroll view. A zoom scale of 1 indicates that the content displays at its normal size. A zoom scale of less than 1 shows a zoomed-out version of the content, and a zoom scale greater than 1 shows the content zoomed in.

To get the minimum zoom scale, you first calculate the required zoom to fit the image view snugly within the scroll view, based on its width. You then calculate the same for the height. You take the minimum of the width and height zoom scales, and set this value for both

func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 1 and

func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 2 of

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 4.

You’ll initially see the entire image fully zoomed-out, and after zooming in, the user will be able to zoom out to this level, too.

Since the

func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 4 defaults to 1, you don’t need to set it. If you set it to greater than 1, the image may appear blurry when the user zooms in on it. If you set it to less than 1, you won’t be able to zoom in to the full image’s resolution.

Finally, you need to update the minimum zoom scale each time the controller updates its subviews. Add the following right before the previous method to do this:

override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() updateMinZoomScaleForSize(view.bounds.size) } Build and run; you should get the following result:

Uiscrollview top-left bottom-right scroll direction swift năm 2024

Now, when you tap on an image, it fits on the screen. You can pan around it and zoom in or out. Awesome!

Note: If you’re unfamiliar with how to perform pinch gestures on the simulator, try holding the Option key while clicking and dragging.

However, there’s still one problem: The image is pinned to the top of the scroll view. It’d sure be nice to center it instead, right?

Centering Your Image

Still in ZoomedPhotoViewController.swift, add the following inside the class extension, right after

extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {

return imageView  
} } 8

//1 func scrollViewDidZoom( scrollView: UIScrollView) { updateConstraintsForSize(view.bounds.size) } //2 func updateConstraintsForSize( size: CGSize) { //3 let yOffset = max(0, (size.height - imageView.frame.height) / 2) imageViewTopConstraint.constant = yOffset imageViewBottomConstraint.constant = yOffset //4 let xOffset = max(0, (size.width - imageView.frame.width) / 2) imageViewLeadingConstraint.constant = xOffset imageViewTrailingConstraint.constant = xOffset view.layoutIfNeeded() } Now, go over this step-by-step:

  1. The scroll view calls func updateMinZoomScaleForSize( size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 6 each time the user zooms. In response, you simply call func updateMinZoomScaleForSize( size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 7 and pass in the view’s bounds size.
  2. func updateMinZoomScaleForSize(_ size: CGSize) { let widthScale = size.width / imageView.bounds.width let heightScale = size.height / imageView.bounds.height let minScale = min(widthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } 7 gets around an annoyance with UIScrollView: If the scroll view’s content size is smaller than its bounds, it places the contents at the top-left of the screen, rather than the center.
  3. You center the image vertically by subtracting the height of extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView  
    
    } } 9 from the override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() updateMinZoomScaleForSize(view.bounds.size) } 1‘s height and dividing the result in half. This value adds padding to the top and bottom extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView  
    
    } } 9 constraints.
  4. Similarly, you calculate an offset for the leading and trailing constraints of extension ZoomedPhotoViewController: UIScrollViewDelegate { func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView  
    
    } } 9, based on the width of the view.

Pat yourself on the back, then build and run your project! Select an image and you’ll end up with a lovely, centered image that you can zoom and pan. :]

How to determine scroll direction in UIScrollView?

To determine the direction, you'll need to use the UIScrollView scrollViewDidScroll delegate. In this sample, I created a variable named lastContentOffset which I use to compare the current content offset with the previous one. If it's greater, then the scrollView is scrolling right.

How to make ScrollView scroll horizontally swift?

If we want to scroll in horizontal direction then we have to add parameter . horizontal in ScrollView. But if we want to scroll in both directions we can mention both like [. vertical, .

How to detect scroll position in Swift?

To detect the scroll position of a scroll view in SwiftUI, we are using the GeometryReader to get the position and size of the scroll view, while GeometryReader is mostly used to access size of the view, it also can be asked to read frame of the current view relative to a given coordinate system.

How to disable horizontal scrolling in UIScrollView swift?

All your imageview textview etc must be in content view. Normally the scrollview won't scroll if the contentsize. width <= width of the scrollview, so if you don't want to do any calculation, safely set the contentsize. width = 0; that will eliminate the scroll for sure.