如何在 swift 中使用 UIPageViewController 在所有视图控制器中显示相同的顶层设计

问题描述 投票:0回答:1

我已经在像这样的故事板中的

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
首先显示。

swift viewcontroller uipageviewcontroller ui-design
1个回答
0
投票

要实现布局,一种方法是创建一个“配置文件”视图控制器,其中包含“欢迎使用配置文件”标签和

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,这样您就可以在构建自己的项目时检查代码和故事板,并查看其实际情况。

© www.soinside.com 2019 - 2024. All rights reserved.