Search code examples
iosswiftxcodeuiscrollview

Why is Page Control not reflecting where I am on the UIScrollView?


After editing my UIScrollView size, page control stopped working.

Example

You can see there are only 3 slides. But (1) Page Control isn't reflecting which slide I'm on and (2) I can only scroll from slide 1 to slide 3.

Here's my code:

func setupSlideScrollView(slides : [Slide]) {
    scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 154)
    scrollView.contentSize = CGSize(width: 188 * CGFloat(slides.count) + CGFloat((slides.count - 1) * 10), height: 153)
    scrollView.isPagingEnabled = true

    var lastCellMaxX: CGFloat = 0
    let constantSpacingBetweenCell: CGFloat = 10

    for i in 0 ..< slides.count {
        slides[i].frame = CGRect(x: lastCellMaxX, y: 0, width: 220, height: 153)
        scrollView.addSubview(slides[i])
        lastCellMaxX += 188 + constantSpacingBetweenCell
    }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let pageIndex = round(scrollView.contentOffset.x/scrollView.frame.size.width)
    pageControl.currentPage = Int(pageIndex)
}

Solution

  • func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // This will always round down to zero 
    // since the contentOffset.x will always be smaller than the frame width...
        let pageIndex = round(scrollView.contentOffset.x/scrollView.frame.size.width) 
    // Possible logic to correct this?
        let pageIndex = scrollView.contentOffset.x / (width of a slide)
        pageControl.currentPage = Int(pageIndex)
    }
    

    -- Updated due to chat --

    Your scrollview's frame is fine. However, you need to add a stackview to hold all your slides in order to scroll through it. Scrollviews are a bit tricky since you can't just add views and expect it to be scrollable.

    Here is test code I used to create a scrollView that contains stackviews.

    func createSlideshow() {
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        let slide1 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
        slide1.backgroundColor = UIColor.red
        let slide2 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
        slide2.backgroundColor = UIColor.blue
        let slide3 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
        slide3.backgroundColor = UIColor.yellow
        let slides: [UIView] = [slide1, slide2, slide3]
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .horizontal
        stackView.alignment = .center
        stackView.distribution = .equalCentering
        stackView.spacing = 10
        for slide in slides {
            stackView.addArrangedSubview(slide)
            slide.widthAnchor.constraint(equalToConstant: slide.frame.width).isActive = true
            slide.heightAnchor.constraint(equalTo: stackView.heightAnchor).isActive = true
        }
        scrollView.addSubview(stackView)
        stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    
        stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
        stackView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
    }