我如何创建一个UIPageViewController,其中所有屏幕都不同,并拥有自己的ViewControllers?

时间:2015-03-07 14:29:22

标签: ios swift storyboard

我想在屏幕之间使用炫酷的滑动动画 - UIPageViewController(是的,你知道介绍画面中的风格),但我在互联网上找到的所有代码和Github都没用我

我在UIViewController界面中找到只有一个Storyboard的演示,几乎所有应用都展示了如何从数组中更改图像源。我读了Apple的参考资料,但我不明白。

我的ViewControllers需要一些Storyboard(我希望以UIPageViewController设计所有屏幕的方式不同,它们将连接到自己的ViewControllers类)将显示在UIPageViewController

当然,如果你知道更好的方法,请说出来!但我需要的功能是,如果你滑动,屏幕会随你移动。

有人知道该怎么做吗?

2 个答案:

答案 0 :(得分:4)

UIPageViewController中没有任何内容需要各种视图控制器是同一个类。因此,只需实现返回不同类型视图控制器的viewControllerBeforeViewControllerviewControllerAfterViewController。如果要从故事板引用子视图控制器,只需为这些场景提供唯一的故事板ID,然后就可以使用instantiateViewControllerWithIdentifier。例如,您可能拥有一系列故事板标识符,并使用它来确定哪种类型的场景是"之前" """"现在的。

有很多方法可以实现这一点,但你可以这样做:

class ViewController: UIPageViewController, UIPageViewControllerDataSource {

    let identifiers = ["A", "B", "C", "D"]  // the storyboard ids for the four child view controllers

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self

        setViewControllers([viewControllerForPage(0)!], direction: .Forward, animated: false, completion: nil)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        var page = (viewController as PageDelegate).pageNumber + 1

        return viewControllerForPage(page)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        var page = (viewController as PageDelegate).pageNumber - 1

        return viewControllerForPage(page)
    }

    func viewControllerForPage(page: Int) -> UIViewController? {
        if page >= 0 && page < identifiers.count {
            let controller = storyboard?.instantiateViewControllerWithIdentifier(identifiers[page]) as? UIViewController
            (controller as PageDelegate).pageNumber = page
            return controller
        }

        return nil
    }
}

显然,如果你想在这里更优雅,你可以维护以前实例化的视图控制器的缓存,但是确保你响应内存压力并在必要时清除缓存。但希望这说明了这样一个事实,即页面视图控制器没有任何内容表明孩子是一类特殊的控制器。

顺便说一下,上面假设每个子视图控制器都符合跟踪页码的协议。

/// Page delegate protocol
///
/// This is a protocol implemented by all of the child view controllers. I'm using it
/// just to keep track of the page number. In practical usage, you might also pass a
/// reference to a model object, too.

@objc protocol PageDelegate {
    var pageNumber: Int { get set }
}

如果你想要一个完全不同的方向,另一种方法是使用标准故事板,你有一个接一个地呈现一个视图控制器的segue,然后为每个视图控制器实现滑动手势识别器,其中从右边滑动执行segue转换到下一个场景(例如IBAction执行performSegueWithIdentifier),另一个滑动手势识别器(从左到右)将关闭视图控制器。

最后,如果您希望这些手势识别器是交互式的(例如,跟随用户的手指),您可以使用自定义过渡以及交互式过渡。有关详细信息,请参阅WWDC 2013视频Custom Transitions Using View Controllers或WWDC 2014视频View Controller Advancements in iOS 8(在视频大约20分钟后,介绍如何使用演示文稿控制器在iOS 8中增强自定义过渡)和{{3 }}

答案 1 :(得分:0)

我认为你可能会利用View Controller Containment。 我们正在处理4个元素。

  • 主视图控制器
  • 滚动视图
  • UIPage控件
  • 详情视图控制器

您可以将滚动视图和页面控件添加为主视图控制器的属性。主控制器将处理滚动逻辑,基本上同步滚动视图和页面控件之间的水平滚动。 滚动视图的内容将由所有详细视图控制器的根视图构成。