1

I am creating a scrollview with a page control. I have a scrollview added to my viewcontroller and inside the scrollview there is a UIImageView. But for some reason I cannot scroll it to the left or right side. Can anyone help me out to fix this problem?

My Code:

    var tutorialImages: [String] = ["1", "2", "3"]
var frame = CGRect.zero

func pageControll() {
    pageControllTutorial.numberOfPages = tutorialImages.count

    for i in 0..<tutorialImages.count {


        imageViewTutorial.frame = frame
        imageViewTutorial.image = UIImage(named: tutorialImages[i])
        scrollViewTutorial.addSubview(imageViewTutorial)
    }

    scrollViewTutorial.contentSize = CGSize(width: imageViewTutorial.frame.size.width * CGFloat(tutorialImages.count), height: imageViewTutorial.frame.size.height)

    scrollViewTutorial.delegate = self
}


func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    var pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
    pageControllTutorial.currentPage = Int(pageNumber)
}
2
  • Is there a reason you want to use explicit frames instead of auto-layout? Commented Feb 20, 2020 at 13:15
  • I was following a tutorial on YouTube and it worked, but not as expected. With auto layout it didn't work at all. Commented Feb 20, 2020 at 13:49

4 Answers 4

1

With the little bit of code you've shown, you're doing a number of things wrong.

Based on this line:

imageViewTutorial.image = UIImage(named: tutorialImages[I])

it looks like you have one UIImageView and you are setting its .image property 3 times, instead of creating 3 different image views.

Also, there is nothing in your code indicating how you are setting the frames of the image views.

I highly recommend using auto-layout instead of explicit frames - makes things much, much easier going forward.

Here is a complete example. It will create a square (1:1 ratio) scroll view 20-pts from the top with 20-pts padding on each side, and a UIPageControl below. It then adds a horizontal UIStackView to the scroll view. That stack view will hold the image views. Once the image views are added, the stack view will automatically define the "scrollable area" -- no need for calculating .contentSize.

Here's what it will look like:

enter image description here

Everything is done in code, so just assign the class of an empty view controller to SlidesExampleViewController ... no @IBOutlet or @IBAction connections needed.

class SlidesExampleViewController: UIViewController, UIScrollViewDelegate {

    lazy var pageControl: UIPageControl = {
        let v = UIPageControl()
        v.backgroundColor = .brown
        return v
    }()

    lazy var scrollView: UIScrollView = {
        let v = UIScrollView(frame: .zero)
        v.backgroundColor = .yellow
        v.delegate = self
        return v
    }()

    lazy var stackView: UIStackView = {
        let v = UIStackView()
        v.axis = .horizontal
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 0
        return v
    }()

    let tutorialImages: [String] = ["1", "2", "3"]

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        stackView.translatesAutoresizingMaskIntoConstraints = false
        pageControl.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(scrollView)
        view.addSubview(pageControl)
        scrollView.addSubview(stackView)

        let v = view.safeAreaLayoutGuide
        let g = scrollView.contentLayoutGuide

        NSLayoutConstraint.activate([

            // constrain scroll view to top, leading, trailing with 20-pts "padding"
            scrollView.topAnchor.constraint(equalTo: v.topAnchor, constant: 20.0),
            scrollView.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 20.0),
            scrollView.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -20.0),

            // constrain scroll view height equal to scroll view width
            scrollView.heightAnchor.constraint(equalTo: scrollView.widthAnchor),

            // constrain stack view to all 4 sides of scroll view's contentLayoutGuide
            stackView.topAnchor.constraint(equalTo: g.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor),

            // constrain stack view height equal to scroll view height
            stackView.heightAnchor.constraint(equalTo: scrollView.heightAnchor),

            // constrain page control width to 80% of scroll view width
            pageControl.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 0.8),

            // constrain page control top to 8-pts below scroll view bottom
            pageControl.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 8.0),

            // constrain page control centerX to centerX of scroll view
            pageControl.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor, constant: 0.0),

        ])

        tutorialImages.forEach { name in
            if let img = UIImage(named: name) {
                let imgView = UIImageView(image: img)
                stackView.addArrangedSubview(imgView)
                imgView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
            }
        }

        pageControl.numberOfPages = tutorialImages.count

        scrollView.isPagingEnabled = true

    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
        pageControl.currentPage = Int(pageIndex)
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Increase the contentSize of scroll view As (number of images * width of image) expecting all image are equal in size.

int startPosition = 0; set the image origin.x

1 image1.frame.origin.x = startPosition; startPosition = startPosition + image1.frame.size.width;

2 image2.frame.origin.x = startPosition; startPosition = startPosition + image2.frame.size.width;

3 image3.frame.origin.x = startPosition; startPosition = startPosition + image3.frame.size.width;

or either you can put these in a for loop to set the frame size of image.

Comments

0

The frame of each UIImageView is being set to CGRect.zero so they all have a 0 height and width, which means your scroll views contentSize is also 0x0. As far as the scroll view is concerned, there's nothing to scroll here.

Do this instead:

let image = UIImage(named: tutorialImages[i])
imageViewTutorial.frame = CGRect(x: widthSoFar, y: 0, width: image.width, height: image.height)
imageViewTutorial.image = image
scrollViewTutorial.addSubview(imageViewTutorial)
widthSoFar += image.size.width

Initialize widthSoFar outside the for loop to 0.

Comments

0

Always Keep the

  1. Scroll view size is greater or equal to Imageview size.
  2. check and keep UIImageView userInteraction Enable.
  3. keep scroll view Content size as big as your number of image like for four image in scoll view then (imageview.frame.size.width*4)

Content size = CGSize(imageview.frame.size.width*4,imageview.frame.size.height).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.