我如何创建一个 UIPageViewController,其中所有屏幕都不同并且有自己的 ViewControllers?
How I can create an UIPageViewController where are all screens different and has own ViewControllers?
我想在屏幕之间使用很酷的滑动动画 - UIPageViewController
(是的,你知道介绍屏幕的样式),但是我在 Internet 上找到的所有代码和 Github对我没用。
我在 Storyboard
界面中发现只有一个 UIViewController
的演示,几乎所有应用程序都展示了如何从数组更改图像源。看了苹果的参考资料,没看懂
我的 Storyboard
需要一些 ViewControllers
(我想将 UIPageViewController
中的所有屏幕设计成不同的,它们将连接到自己的 ViewControllers
类) 谁将出现在 UIPageViewController
.
当然,如果您知道更好的方法,请说出来!但我需要的是滑动屏幕随你移动的功能。
有人知道怎么做吗?
我认为您可以利用 View Controller Containment。
我们在这里处理 4 个元素。
- 主视图控制器
- 滚动视图
- UIPage 控件
- 详细视图控制器
您可以添加滚动视图和页面控件作为主视图控制器的属性。主控制器将处理滚动逻辑,基本上同步滚动视图和页面控件之间的水平滚动。
滚动视图的内容将由所有详细视图控制器的根视图构成。
UIPageViewController
中没有任何内容要求各种视图控制器相同 class。因此,只需实现 viewControllerBeforeViewController
和 viewControllerAfterViewController
以及 return 不同类型的视图控制器。如果你想从故事板中引用子视图控制器,只需给那些场景唯一的故事板 ID,然后你就可以使用 instantiateViewControllerWithIdentifier
。例如,您可能有一个故事板标识符数组,并使用它来确定哪种场景是 "before" 和 "after" 当前场景。
有很多方法可以实现这一点,但您可以这样做:
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
}
}
显然,如果你想在这里更优雅,你可以维护一个以前实例化的视图控制器的缓存,但确保你响应内存压力并在必要时清除该缓存。但希望这能说明这样一个事实,即页面视图控制器没有任何内容表明子级是控制器的特定 class。
顺便说一句,上面假设每个子视图控制器都符合一个协议来跟踪页码。
/// 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 }
}
如果你想走完全不同的方向,另一种方法是使用标准故事板,你有一个接一个呈现视图控制器的 segues,然后为每个视图控制器实现滑动手势识别器,从右边滑动执行 segue 以过渡到下一个场景(例如 IBAction
执行 performSegueWithIdentifier
),另一个滑动手势识别器(从左到右)将关闭视图控制器。
最后,如果您希望这些手势识别器具有交互性(例如跟随用户的手指),您可以使用自定义转换,并结合交互式转换。有关详细信息,请参阅 WWDC 2013 视频 Custom Transitions Using View Controllers or WWDC 2014 videos View Controller Advancements in iOS 8 (which, about 20 minutes into the video, describes how custom transitions have been enhanced in iOS 8 with presentation controllers) and A Look Inside Presentation Controllers。
我想在屏幕之间使用很酷的滑动动画 - UIPageViewController
(是的,你知道介绍屏幕的样式),但是我在 Internet 上找到的所有代码和 Github对我没用。
我在 Storyboard
界面中发现只有一个 UIViewController
的演示,几乎所有应用程序都展示了如何从数组更改图像源。看了苹果的参考资料,没看懂
我的 Storyboard
需要一些 ViewControllers
(我想将 UIPageViewController
中的所有屏幕设计成不同的,它们将连接到自己的 ViewControllers
类) 谁将出现在 UIPageViewController
.
当然,如果您知道更好的方法,请说出来!但我需要的是滑动屏幕随你移动的功能。
有人知道怎么做吗?
我认为您可以利用 View Controller Containment。 我们在这里处理 4 个元素。
- 主视图控制器
- 滚动视图
- UIPage 控件
- 详细视图控制器
您可以添加滚动视图和页面控件作为主视图控制器的属性。主控制器将处理滚动逻辑,基本上同步滚动视图和页面控件之间的水平滚动。 滚动视图的内容将由所有详细视图控制器的根视图构成。
UIPageViewController
中没有任何内容要求各种视图控制器相同 class。因此,只需实现 viewControllerBeforeViewController
和 viewControllerAfterViewController
以及 return 不同类型的视图控制器。如果你想从故事板中引用子视图控制器,只需给那些场景唯一的故事板 ID,然后你就可以使用 instantiateViewControllerWithIdentifier
。例如,您可能有一个故事板标识符数组,并使用它来确定哪种场景是 "before" 和 "after" 当前场景。
有很多方法可以实现这一点,但您可以这样做:
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
}
}
显然,如果你想在这里更优雅,你可以维护一个以前实例化的视图控制器的缓存,但确保你响应内存压力并在必要时清除该缓存。但希望这能说明这样一个事实,即页面视图控制器没有任何内容表明子级是控制器的特定 class。
顺便说一句,上面假设每个子视图控制器都符合一个协议来跟踪页码。
/// 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 }
}
如果你想走完全不同的方向,另一种方法是使用标准故事板,你有一个接一个呈现视图控制器的 segues,然后为每个视图控制器实现滑动手势识别器,从右边滑动执行 segue 以过渡到下一个场景(例如 IBAction
执行 performSegueWithIdentifier
),另一个滑动手势识别器(从左到右)将关闭视图控制器。
最后,如果您希望这些手势识别器具有交互性(例如跟随用户的手指),您可以使用自定义转换,并结合交互式转换。有关详细信息,请参阅 WWDC 2013 视频 Custom Transitions Using View Controllers or WWDC 2014 videos View Controller Advancements in iOS 8 (which, about 20 minutes into the video, describes how custom transitions have been enhanced in iOS 8 with presentation controllers) and A Look Inside Presentation Controllers。