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.
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:
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
Firebase Notification Records/Log API
How to Handle Different Orientations in Ios
How to Crop a Uiimageview to a New Uiimage in 'Aspect Fill' Mode
Didregisterforremotenotificationswithdevicetoken Not Called in Ios8, But Didregister...Settings Is
How to Disable Copy Paste Option from Uitextfield Programmatically
Setting Custom Uitableviewcells Height
Swift Days Between Two Nsdates
Change Uitableview Height Dynamically
Didselectrowatindexpath Not Working, Swift 3
How to Add an In-App Purchase to an iOS Application
What Are Sprite Kit'S "Category Mask" and "Collision Mask"
Issue Detecting Button Cellforrowat
Add "...Read More" to the End of Uilabel
Disable Uiscrollview Scrolling When Uitextfield Becomes First Responder