Home > Software engineering >  How to change starting page to another page in UIScrollView
How to change starting page to another page in UIScrollView

Time:05-29

I've created a scroll view where the user can cycle through the pages that I've assigned. The first button leads to page1 as the starting page. However I would like the current starting page to be page 2 when I press button 2 that leads me to the page views but I can't seem to find a way around it,

My code in the ViewController is as follows:

var pages : [View] {
    
    get {
        let page1: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page1.colorLabel.text = "Apartment A3"
        page1.priceLabel.text = "N$ 504 500"
        page1.imageView.image = UIImage(named: "apartment_a3_1")
        
        
        let page2: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page2.colorLabel.text = "Apartment A4"
        page2.priceLabel.text = "N$ 481 000"
        page2.imageView.image = UIImage(named: "apartment_a4_1")
        
        let page3: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page3.colorLabel.text = "Apartment A5"
        page3.priceLabel.text = "N$ 541 000"
        page3.imageView.image = UIImage(named: "apartment_a5_1")
        
        let page4: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page4.colorLabel.text = "Apartment A6"
        page4.priceLabel.text = "N$ 553 000"
        page4.imageView.image = UIImage(named: "apartment_a6_1")
        
        let page5: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page5.colorLabel.text = "Apartment A8"
        page5.priceLabel.text = "N$ 588 000"
        page5.imageView.image = UIImage(named: "apartment_a8_1")
        
        let page6: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page6.colorLabel.text = "Apartment A9"
        page6.priceLabel.text = "N$ 775 000"
        page6.imageView.image = UIImage(named: "apartment_a9a1")
        
        let page7: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
        page7.colorLabel.text = "Apartment A12"
        page7.priceLabel.text = "N$ 775 000"
        page7.imageView.image = UIImage(named: "apartment_a12_a")
        

        return [page1, page2, page3, page4, page5, page6, page7]
    }
}

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var pageControl: UIPageControl!

override func viewDidLoad() {
    super.viewDidLoad()
    
    //view.bringSubviewToFront(pageControl)
    
    setupScrollView(pages: pages)
    
    pageControl.numberOfPages = pages.count
    pageControl.currentPage = 0
}

func setupScrollView(pages: [View]) {
    //scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
    scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(pages.count), height: view.frame.height)
    scrollView.isPagingEnabled = true
    
    
    for i in 0 ..< pages.count {
        pages[i].frame = CGRect(x: view.frame.width * CGFloat(i), y: 0, width: view.frame.width, height: view.frame.height)
        scrollView.addSubview(pages[i])
    }
}

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

I've tried to change PageControl.currentPage = 0 to 1 but no luck.

CodePudding user response:

Couple notes...

First, you should be using auto-layout -- makes it much easier to manage the frames and the scroll view content.

Second, keep your size calculations relative to the scroll view's frame, not the view's frame... it will keep things more consistent, and avoid problems if you decide to make the scroll view not "full screen" (which you shouldn't do anyway, because you always want to respect the safe-area).

Third, if you only have 7 "pages" this approach should be fine. If you may have more than that, you can run into memory issues. If that's the case, you should look into either a UICollectionView or UIPageViewController.

So, assuming you can stick with the scroll view approach...

To "start at the second page" you can set the scroll view's .contentOffset.x during viewDidLayoutSubviews.

Start by adding a var property to track the width of the scroll view's frame:

var scrollViewWidth: CGFloat = 0

then implement viewDidLayoutSubviews():

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    // we only want to call this once
    if scrollViewWidth != scrollView.frame.width {
        scrollViewWidth = scrollView.frame.width
        scrollView.contentOffset.x = scrollView.frame.width
    }
}

Here's a quick look at some changes you might want to make to take advantage of the benefits of auto-layout:

class ViewController: UIViewController {

    var pages : [View] {
        
        get {
            let page1: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page1.colorLabel.text = "Apartment A3"
            page1.priceLabel.text = "N$ 504 500"
            page1.imageView.image = UIImage(named: "apartment_a3_1")
            
            
            let page2: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page2.colorLabel.text = "Apartment A4"
            page2.priceLabel.text = "N$ 481 000"
            page2.imageView.image = UIImage(named: "apartment_a4_1")
            
            let page3: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page3.colorLabel.text = "Apartment A5"
            page3.priceLabel.text = "N$ 541 000"
            page3.imageView.image = UIImage(named: "apartment_a5_1")
            
            let page4: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page4.colorLabel.text = "Apartment A6"
            page4.priceLabel.text = "N$ 553 000"
            page4.imageView.image = UIImage(named: "apartment_a6_1")
            
            let page5: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page5.colorLabel.text = "Apartment A8"
            page5.priceLabel.text = "N$ 588 000"
            page5.imageView.image = UIImage(named: "apartment_a8_1")
            
            let page6: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page6.colorLabel.text = "Apartment A9"
            page6.priceLabel.text = "N$ 775 000"
            page6.imageView.image = UIImage(named: "apartment_a9a1")
            
            let page7: View = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! View
            page7.colorLabel.text = "Apartment A12"
            page7.priceLabel.text = "N$ 775 000"
            page7.imageView.image = UIImage(named: "apartment_a12_a")
            
            
            return [page1, page2, page3, page4, page5, page6, page7]
        }
    }

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var pageControl: UIPageControl!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupScrollView(pages: pages)
        
        pageControl.numberOfPages = pages.count
        pageControl.currentPage = 0
    }
    
    var scrollViewWidth: CGFloat = 0

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // we only want to call this once
        if scrollViewWidth != scrollView.frame.width {
            scrollViewWidth = scrollView.frame.width
            scrollView.contentOffset.x = scrollView.frame.width
        }
    }

    func setupScrollView(pages: [View]) {
        
        let stack = UIStackView()
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        let clg = scrollView.contentLayoutGuide
        let flg = scrollView.frameLayoutGuide
        
        scrollView.addSubview(stack)
        NSLayoutConstraint.activate([
            // constrain all 4 sides of stack view to scroll view's Content Layout Guide
            stack.topAnchor.constraint(equalTo: clg.topAnchor),
            stack.leadingAnchor.constraint(equalTo: clg.leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: clg.trailingAnchor),
            stack.bottomAnchor.constraint(equalTo: clg.bottomAnchor),
            
            // constrain height of stack view to scroll view's Frame Layout Guide
            stack.heightAnchor.constraint(equalTo: flg.heightAnchor),
        ])
        
        for i in 0 ..< pages.count {
            // add each page to the stack view
            stack.addArrangedSubview(pages[i])
            // make each page the same width as the scroll view's Frame Layout Guide width
            pages[i].widthAnchor.constraint(equalTo: flg.widthAnchor).isActive = true
        }
        
        scrollView.isPagingEnabled = true
        scrollView.delegate = self

    }
    
    @IBAction func pageControlChanged(_ sender: UIPageControl) {
        UIView.animate(withDuration: 0.3, animations: {
            self.scrollView.contentOffset.x = CGFloat(sender.currentPage) * self.scrollView.frame.width
        })
    }
}
extension ViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageIndex = round(scrollView.contentOffset.x / scrollView.frame.width)
        pageControl.currentPage = Int(pageIndex)
    }
}
  • Related