我有一个UIPageViewController,在我们向左或向右滑动翻页时工作正常。
class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}
现在我打算在页面上提供“上一页/下一页”按钮,以便通过点击这些按钮来翻页。
我应该如何在程序中触发左滑/右滑的行为或者实现页面翻转呢?
注意
这是一个有关Swift语言的问题,不涉及Objective-C。
我有一个UIPageViewController,在我们向左或向右滑动翻页时工作正常。
class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}
现在我打算在页面上提供“上一页/下一页”按钮,以便通过点击这些按钮来翻页。
我应该如何在程序中触发左滑/右滑的行为或者实现页面翻转呢?
这是一个有关Swift语言的问题,不涉及Objective-C。
通常情况下不需要调整页面索引等内容。很可能您已经实现了 dataSource: UIPageViewControllerDataSource
,它已经包含了您需要显示上一个或下一个视图控制器的所有内容。
Swift 5 示例:
extension UIPageViewController {
func goToNextPage() {
guard let currentViewController = self.viewControllers?.first else { return }
guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }
setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
}
func goToPreviousPage() {
guard let currentViewController = self.viewControllers?.first else { return }
guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }
setViewControllers([previousViewController], direction: .reverse, animated: false, completion: nil)
}
}
这样你就能确保你要过渡到的页面正好是PageViewController
内置手势会触发的内容。
presentationIndexForPageViewController
。在我的pageItemViewController
中,我声明了一个叫做itemIndex
的变量。我该如何在这个扩展中设置它? - Adrian以下是 SuitedSloth 的回答的 Swift 3 版本(对 animated
参数进行了微小调整,以使其默认情况下具有动画效果,但仍可在函数中接受参数),如果有人需要:
extension UIPageViewController {
func goToNextPage(animated: Bool = true) {
guard let currentViewController = self.viewControllers?.first else { return }
guard let nextViewController = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) else { return }
setViewControllers([nextViewController], direction: .forward, animated: animated, completion: nil)
}
func goToPreviousPage(animated: Bool = true) {
guard let currentViewController = self.viewControllers?.first else { return }
guard let previousViewController = dataSource?.pageViewController(self, viewControllerBefore: currentViewController) else { return }
setViewControllers([previousViewController], direction: .reverse, animated: animated, completion: nil)
}
}
{ completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) }
- Andrew Duncancompleted in
,然后在新行上是 self.delegate?.pageViewController...
。 - josher932这里是使用委托的Swift 4实现。
由于我还使用了UIPageViewControllerDelegate,并且大多数setViewController解决方案都没有调用委托方法。
感谢Andrew Duncan的评论,关于委托的问题。
// Functions for clicking next and previous in the navbar, Updated for swift 4
@objc func toNextArticle(){
guard let currentViewController = self.viewControllers?.first else { return }
guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }
// Has to be set like this, since else the delgates for the buttons won't work
setViewControllers([nextViewController], direction: .forward, animated: true, completion: { completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
}
@objc func toPreviousArticle(){
guard let currentViewController = self.viewControllers?.first else { return }
guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }
// Has to be set like this, since else the delgates for the buttons won't work
setViewControllers([previousViewController], direction: .reverse, animated: true, completion:{ completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
}
private func slideToPage(index: Int, completion: (() -> Void)?) {
let count = //Function to get number of viewControllers
if index < count {
if index > currentPageIndex {
if let vc = viewControllerAtIndex(index) {
self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: { (complete) -> Void in
self.currentPageIndex = index
completion?()
})
}
} else if index < currentPageIndex {
if let vc = viewControllerAtIndex(index) {
self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Reverse, animated: true, completion: { (complete) -> Void in
self.currentPageIndex = index
completion?()
})
}
}
}
}
viewControllerAtIndex(index: Int) -> UIViewController?
是我自己编写的函数,用于获取正确的视图控制器以进行滑动。
currentPageIndex
是从哪里来的? - ataravaticurrentPageIndex
是一个本地变量,您可以定义它以便跟踪当前页面。 - Swinny89在这里留下一些内容,以防任何人想要使用定义的协议来编程地导航和更改视图控制器。
@objc protocol AppWalkThroughDelegate {
@objc optional func goNextPage(forwardTo position: Int)
@objc optional func goPreviousPage(fowardTo position: Int)
}
使用上述协议并确认根UIPageViewController来管理视图控制器之间的导航。
下面是一个示例:
class AppWalkThroughViewController: UIPageViewController, UIPageViewControllerDataSource, AppWalkThroughDelegate {
// Add list of view controllers you want to load
var viewControllerList : [UIViewControllers] = {
let firstViewController = FirstViewController()
let secondViewController = SecondViewController()
// Assign root view controller as first responder
secondViewController.delegate = self
let thirdViewController = ThirdViewController()
}
override func viewDidLoad() {
super.viewDidLoad()
}
// Navigate to next page
func goNextPage(fowardTo position: Int) {
let viewController = self.viewControllerList[position]
setViewControllers([viewController], direction:
UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
}
完成上述步骤后,需要使UIPageViewController向前或向后移动的子视图控制器可以通过将特定数字传递给委托属性来使用AppWalkThroughDelegate方法。
以下是示例:按钮按下后调用的委托方法
class SecondViewController: UIViewController {
var delegate: AppWalkThroughDelegate!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func goNextPage(_ sender: Any) {
// Can be any number but not outside viewControllerList bounds
delegate.goNextPage!(fowardTo: 2)
}
}