How to Turn Page Programmatically in Uipageviewcontroller

Is it possible to Turn page programmatically in UIPageViewController?

Yes it is possible with the method:

- (void)setViewControllers:(NSArray *)viewControllers 
direction:(UIPageViewControllerNavigationDirection)direction
animated:(BOOL)animated
completion:(void (^)(BOOL finished))completion;`

That is the same method used for setting up the first view controller on the page. Similar, you can use it to go to other pages.

Wonder why viewControllers is an array, and not a single view controller?

That's because a page view controller could have a "spine" (like in iBooks), displaying 2 pages of content at a time. If you display 1 page of content at a time, then just pass in a 1-element array.

An example in Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)

iOS Swift: UIPageViewController - Turning page programmatically

Use this funtion and set the transition style for the animation you want.

Sample Image

Sample Image

Go to the next Page programmatically within a UIPageViewController

You need to set the delegate property of the view controller instance that will be displayed:

func viewControllerAtIndex(index: Int) -> UIViewController? {

let vc = storyboard?.instantiateViewControllerWithIdentifier(pages[index])
if index == 0 {
let userInputViewController =vc as! userInputViewController
userInputViewController.delegate = self
}
return vc
}

Also, by convention, classes start with an upper case letter, so it should be UserInputViewController

Create partial-screen UIPageViewController programmatically

UIContainerView is really just a Storyboard convenience. It adds a normal UIView and allows you to connect a View Controller as its "embedded content."

But, under the hood, it is doing exactly what you can do from code:

  • add a UIView to your main view that you will use as the "container"
  • instantiate your page view controller
  • use addChild(_ childController: UIViewController) to add that page view controller as a child controller
  • add the child VC's view to your "container" view

Here is a complete example:

//
// Created by Don Mag on 5/31/19.
//

import UIKit

// simple example view controller
// has a label 90% of the width, centered X and Y
class ExampleViewController: UIViewController {

let theLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .white
v.textAlignment = .center
return v
}()

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(theLabel)
NSLayoutConstraint.activate([
theLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
theLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
theLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),
])

}

}

// example Page View Controller
class MyPageViewController: UIPageViewController {

let colors: [UIColor] = [
.red,
.green,
.blue,
.cyan,
.yellow,
.orange
]

var pages: [UIViewController] = [UIViewController]()

override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
}

required init?(coder: NSCoder) {
super.init(coder: coder)
}

override func viewDidLoad() {
super.viewDidLoad()

dataSource = self
delegate = nil

// instantiate "pages"
for i in 0.. let vc = ExampleViewController()
vc.theLabel.text = "Page: \(i)"
vc.view.backgroundColor = colors[i]
pages.append(vc)
}

setViewControllers([pages[0]], direction: .forward, animated: false, completion: nil)
}

}

// typical Page View Controller Data Source
extension MyPageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

guard let viewControllerIndex = pages.index(of: viewController) else { return nil }

let previousIndex = viewControllerIndex - 1

guard previousIndex >= 0 else { return pages.last }

guard pages.count > previousIndex else { return nil }

return pages[previousIndex]
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.index(of: viewController) else { return nil }

let nextIndex = viewControllerIndex + 1

guard nextIndex < pages.count else { return pages.first }

guard pages.count > nextIndex else { return nil }

return pages[nextIndex]
}
}

// typical Page View Controller Delegate
extension MyPageViewController: UIPageViewControllerDelegate {

// if you do NOT want the built-in PageControl (the "dots"), comment-out these funcs

func presentationCount(for pageViewController: UIPageViewController) -> Int {
return pages.count
}

func presentationIndex(for pageViewController: UIPageViewController) -> Int {

guard let firstVC = pageViewController.viewControllers?.first else {
return 0
}
guard let firstVCIndex = pages.index(of: firstVC) else {
return 0
}

return firstVCIndex
}
}

class MyTestViewController: UIViewController {

let myContainerView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .gray
return v
}()

var thePageVC: MyPageViewController!

override func viewDidLoad() {
super.viewDidLoad()

// add myContainerView
view.addSubview(myContainerView)

// constrain it - here I am setting it to
// 40-pts top, leading and trailing
// and 200-pts height
NSLayoutConstraint.activate([
myContainerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
myContainerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
myContainerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),
myContainerView.heightAnchor.constraint(equalToConstant: 200.0),
])

// instantiate MyPageViewController and add it as a Child View Controller
thePageVC = MyPageViewController()
addChild(thePageVC)

// we need to re-size the page view controller's view to fit our container view
thePageVC.view.translatesAutoresizingMaskIntoConstraints = false

// add the page VC's view to our container view
myContainerView.addSubview(thePageVC.view)

// constrain it to all 4 sides
NSLayoutConstraint.activate([
thePageVC.view.topAnchor.constraint(equalTo: myContainerView.topAnchor, constant: 0.0),
thePageVC.view.bottomAnchor.constraint(equalTo: myContainerView.bottomAnchor, constant: 0.0),
thePageVC.view.leadingAnchor.constraint(equalTo: myContainerView.leadingAnchor, constant: 0.0),
thePageVC.view.trailingAnchor.constraint(equalTo: myContainerView.trailingAnchor, constant: 0.0),
])

thePageVC.didMove(toParent: self)
}

}

Result:

Sample Image

Turn page programmatically in UIPageViewController when using UIPageViewControllerDataSource?

The Method mentioned in the answer ( setViewControllers:direction:animated:completion: ) sets the current view controller and is exactly what you need.
With the first param you define the view controller(s), you want to display. Use one if you don't have a spine, if you book is left/right use two.



Related Topics



Leave a reply



Submit