如何在 UIScrollView 中将起始页更改为另一页

How to change starting page to another page in UIScrollView

我创建了一个滚动视图,用户可以在其中循环浏览我分配的页面。第一个按钮指向 page1 作为起始页。但是,当我按下按钮 2 时,我希望当前的起始页是第 2 页,这会引导我进入页面视图,但我似乎找不到解决方法,

我在ViewController中的代码如下:

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)
    }
}

我试过将 PageControl.currentPage = 0 更改为 1 但没有成功。

情侣笔记...

首先,您应该使用 auto-layout -- 可以更轻松地管理框架和滚动视图内容。

其次,保持你的尺寸计算相对于滚动视图的框架,而不是视图的框架......它会让事情更加一致,并避免问题,如果你决定滚动视图不是“全屏”(无论如何你都不应该这样做,因为你总是想要尊重 safe-area)。

第三,如果你只有 7 个“页面”,这种方法应该没问题。如果你可能有更多,你可以 运行 进入内存问题。如果是这种情况,您应该查看 UICollectionViewUIPageViewController.

因此,假设您可以坚持使用滚动视图方法...

要“从第二页开始”,您可以在 viewDidLayoutSubviews 期间设置滚动视图的 .contentOffset.x

首先添加一个 var 属性 来跟踪滚动视图框架的宽度:

var scrollViewWidth: CGFloat = 0

然后执行 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
    }
}

快速浏览一下您可能希望进行的一些更改以利用 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)
    }
}

编辑 - 回复评论...

如果你有“转到页面”的按钮,你可以实现这样的功能:

func showPage(_ pg: Int) {
    UIView.animate(withDuration: 0.3, animations: {
        self.scrollView.contentOffset.x = CGFloat(pg - 1) * self.scrollView.frame.width
    })
}

并调用它,例如:

showPage(5)