如何在 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 个“页面”,这种方法应该没问题。如果你可能有更多,你可以 运行 进入内存问题。如果是这种情况,您应该查看 UICollectionView
或 UIPageViewController
.
因此,假设您可以坚持使用滚动视图方法...
要“从第二页开始”,您可以在 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)
我创建了一个滚动视图,用户可以在其中循环浏览我分配的页面。第一个按钮指向 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 个“页面”,这种方法应该没问题。如果你可能有更多,你可以 运行 进入内存问题。如果是这种情况,您应该查看 UICollectionView
或 UIPageViewController
.
因此,假设您可以坚持使用滚动视图方法...
要“从第二页开始”,您可以在 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)