我已经在像这样的故事板中的
MainSegPageViewController
中创建了顶级设计,我还有另外2个视图控制器。现在我需要在所有三个视图控制器中使用相同的上部设计。那么如何仅在这个 wight 区域显示 2 个视图控制器呢?那可能吗?如果是的话请解释一下
代码:使用此代码最初我得到
ViewController1
为什么?最初如何显示MainSegPageViewController
?以及当我单击 ViewController1
时如何在白色区域显示 STEP 2
。请指导我。
import UIKit
class MainSegPageViewController: UIPageViewController {
private(set) lazy var subViewcontrollers: [UIViewController] = {
return [
UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: "ViewController1"),
UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: "ViewController2")
]
}()
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
modalPresentationStyle = .formSheet
if let firstViewController = subViewcontrollers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
setUpNavigationBar(with: "Pagination vc", isBackNeed: true)
self.navigationController?.navigationBar.isHidden = false
}
}
// MARK: UIPageViewControllerDataSource
extension MainSegPageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = subViewcontrollers.firstIndex(of:viewController)
else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard subViewcontrollers.count > previousIndex else {
return nil
}
if previousIndex == 2 {
return nil
}
return subViewcontrollers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = subViewcontrollers.firstIndex(of:viewController)
else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = subViewcontrollers.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
if nextIndex == 3 {
return nil
}
return subViewcontrollers[nextIndex]
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return subViewcontrollers.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
guard let firstViewController = viewControllers?.first, let firstViewControllerIndex = subViewcontrollers.firstIndex(of: firstViewController) else {
return 0
}
return firstViewControllerIndex
}
}
我正在通过这样的侧面菜单到达
MainSegPageViewController
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "MainSegPageViewController") as? MainSegPageViewController
self.navigationController?.pushViewController(vc!, animated: true)
o/p: 使用代码最初我得到
ViewController1
屏幕,但我需要 MainSegPageViewController
首先显示。
要实现布局,一种方法是创建一个“配置文件”视图控制器,其中包含“欢迎使用配置文件”标签和
UISegmentedControl
,然后将 UIPageViewController
嵌入到容器视图中。
因此,由于您的帖子说您正在导航控制器中推送此布局,因此我们从故事板中的此开始:
按钮将连接到此代码:
@IBAction func profileButtonTapped(_ sender: Any) {
if let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ProfileViewController") as? ProfileViewController {
navigationController?.pushViewController(vc, animated: true)
}
}
然后,在故事板中布局
ProfileViewController
,如下所示:
大视野是
UIContainerView
:
我们在其中嵌入了一个典型的
UIPageViewController
。
假设您有页面视图控制器的工作代码,则可以运行该代码,并且您将能够在页面中来回滑动。
接下来,我们需要添加一些代码,以便点击分段将更改页面。
我们可以像这样设置
ProfileViewController
:
class ProfileViewController: UIViewController {
@IBOutlet var stepsSegCtrl: UISegmentedControl!
// we will want a reference to the embedded MainSegPageViewController
// so we can tell it to change page when the segmented control is tapped
var mainSegPageVC: MainSegPageViewController?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Pagination VC"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// this is called because we've embedded the controller in a container view
if let pgVC = segue.destination as? MainSegPageViewController {
// save reference so we can access it when the segmented control is tapped
mainSegPageVC = pgVC
}
}
@IBAction func segCtrlChanged(_ sender: UISegmentedControl) {
// safely unwrap
if let pgVC = mainSegPageVC {
pgVC.gotoPage(pg: sender.selectedSegmentIndex)
}
}
}
在容器视图中嵌入控制器时,我们会自动获得一个
segue
,我们可以在其中获取对嵌入页面视图控制器的引用。
如果我们将此函数添加到我们的
MainSegPageViewController
类中:
public func gotoPage(pg: Int) {
let curPg = presentationIndex(for: self)
if pg > curPg {
setViewControllers([subViewcontrollers[pg]],
direction: .forward,
animated: true,
completion: nil)
} else {
setViewControllers([subViewcontrollers[pg]],
direction: .reverse,
animated: true,
completion: nil)
}
}
我们现在可以从分段控件更改页面。
最后,我们需要添加一个
closure
,以便页面视图控制器可以在用户拖动到新页面时通知“父”控制器。
所以,在
MainSegPageViewController
类中,我们添加这个属性:
var pageChanged: ((Int) -> ())?
并实施:
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
// user dragged to a new page, so inform the parent controller
pageChanged?(presentationIndex(for: self))
}
我们将该闭包设置回
prepare(for segue:...)
回到 ProfileViewController
:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// this is called because we've embedded the controller in a container view
if let pgVC = segue.destination as? MainSegPageViewController {
// set the closure
pgVC.pageChanged = { [weak self] pg in
guard let self = self else { return }
// user dragged to a new page, so update the segmented control
self.stepsSegCtrl.selectedSegmentIndex = pg
}
// save reference so we can access it when the segmented control is tapped
mainSegPageVC = pgVC
}
}
我在这里发布了一个完整的项目 - https://github.com/DonMag/ContainerPageViewController,这样您就可以在构建自己的项目时检查代码和故事板,并查看其实际情况。