ios - tutorial - uipageviewcontroller swift 4
iOS Swift: UIPageViewController-Pasando página programáticamente (6)
Tengo un UIPageViewController, que funciona bien cuando pasamos a la izquierda o la derecha para pasar las páginas.
class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}
Ahora tengo la intención de proporcionar el botón Anterior / Siguiente en la página también, de modo que las páginas puedan girarse haciendo clic en estos botones.
¿Cómo puedo activar el comportamiento de barrido hacia la izquierda o hacia la derecha O pasar las páginas programáticamente?
Nota
Esta es una pregunta para el lenguaje Swift , no para Objective-C.
Aquí está la rápida implementación 4 con los delegados también.
Ya que también uso UIPageViewControllerDelegate, y la mayoría de las soluciones de setViewController no llamaron a los métodos delegados.
Gracias a Andrew Duncan por su comentario sobre el delegado.
// 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) })
}
Aquí hay una implementación rápida de esto:
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?
es mi propia función para obtener el controlador de vista correcto para deslizar a.
En general, no hay necesidad de jugar con los índices de páginas y qué no. Es probable que ya esté implementando un dataSource: UIPageViewControllerDataSource
, que tiene todo lo que necesita para obtener un ViewController anterior o siguiente para mostrar.
Swift 2.2 Ejemplo:
extension UIPageViewController {
func goToNextPage(){
guard let currentViewController = self.viewControllers?.first else { return }
guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfterViewController: 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, viewControllerBeforeViewController: currentViewController ) else { return }
setViewControllers([previousViewController], direction: .Reverse, animated: false, completion: nil)
}
}
De esta manera, se garantiza que las páginas a las que está haciendo la transición son exactamente lo que los gestos integrados de PageViewController dispararían.
La versión Swift 3 de la de (con un pequeño ajuste en el parámetro animated
, ya que necesitaba que se animara de forma predeterminada, pero aún tomando un parámetro en la función) en caso de que alguien lo necesite:
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)
}
}
Simplemente omitiendo esto aquí en caso de que alguien quiera usar un protocolo definido para navegar y cambiar programadores de vista.
@objc protocol AppWalkThroughDelegate {
@objc optional func goNextPage(forwardTo position: Int)
@objc optional func goPreviousPage(fowardTo position: Int)
}
Utilice el protocolo anterior y confirme como root UIPageViewController para administrar la navegación entre los controladores de vista.
Ejemplo abajo:
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()
self.dataSource = self
}
// Navigate to next page
func goNextPage(fowardTo position: Int) {
let viewController = self.viewControllerList[position]
setViewControllers([viewController], direction:
UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
}
Una vez logrado todo eso, los controladores de vista secundarios que necesitan hacer que UIPageViewController pase a la página siguiente o anterior pueden usar los métodos de AppWalkThroughDelegate pasando un número específico a la propiedad delegada.
Ejemplo a continuación: Método de delegado invocado una vez que se presiona el botón
class SecondViewController: UIViewController {
var delegate: AppWalkThroughDelegate!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
}
@IBAction func goNextPage(_ sender: Any) {
// Can be any number but not outside viewControllerList bounds
delegate.goNextPage!(fowardTo: 2)
}
}
Utilice esta función y configure el estilo de transición para la animación que desea.