Using next button on PageViewController
You need to use this inside a UIPageViewController
subclass
self.setViewControllers([someVC], direction: .forward, animated: true, completion: nil)
how to be back to previous VC or next VC from a view controller inside UIPageViewController?
So, in your RootPageViewController
, you could have a function there that will use setViewControllers
.
And that setViewControllers
is described as:
// Set visible view controllers, optionally with animation. Array
should only include view controllers that will be visible after the
animation has completed.
// For transition style 'UIPageViewControllerTransitionStylePageCurl', if 'doubleSided' is
'YES' and the spine location is not
'UIPageViewControllerSpineLocationMid', two view controllers must be
included, as the latter view controller is used as the back.
So let's try to have a Next
function.
func next() {
let vcs = self.viewControllerList
//or self.viewControllers
let currentPage = self.pageControl.currentPage
let nextPage = currentPage + 1
if nextPage < vcs.count {
let nextVC = vcs[nextPage]
self.setViewControllers([nextVC], direction: .forward, animated: true) { _ in
self.pageControl.currentPage = nextPage
}
}
}
As you can see, we are safely getting a viewController from the vcs
you made in your code, which contains all the pages. And after we get the next viewController, if there's any, we use the setViewControllers
. To make it better, we're setting the currentPage
of your pageControl
to tell which circle at the bottom of your pageController to be colored.
And then from your BlueVC
, get a reference of your pageController. How? By accessing the self.parent
and cast it as your RootPageViewController
. Like so:
@IBAction func next(_ sender: Any) {
if let parentVC = self.parent as? RootPageViewController {
parentVC.next()
}
}
Now, it's your task to implement the previous
function.
iOS: UIPageViewController - Use button to jump to next page
You can programmatically set the currently displayed view controller with a transition animation using setViewControllers:direction:animated:completion:
on your page view controller.
Here is an example that presents view controllers with random background colors. You can adjust this to use your specific view controllers.
- (void)viewDidLoad
{
[super viewDidLoad];
self.pvc = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pvc.view.frame = CGRectInset(self.view.bounds, 200, 200);
[self.view addSubview:self.pvc.view];
[self.pvc setViewControllers:@[[self randomVC]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}
-(UIViewController*)randomVC
{
UIViewController *vc = [[UIViewController alloc] init];
UIColor *color = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1];
vc.view.backgroundColor = color;
return vc;
}
- (IBAction)previousButtonPressed:(id)sender {
[self.pvc setViewControllers:@[[self randomVC]] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}
- (IBAction)nextButtonPressed:(id)sender {
[self.pvc setViewControllers:@[[self randomVC]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}
How do I navigate forward and backward within UIPageViewController using buttons?
I think what you're looking for is here. But this is another way.
UIPageViewController has an instance method transition. The snippet below will move from the first to the second page child view controller.
pageViewController.transition(from: pageViewController.viewControllers[0], to: pageViewController.viewControllers[1], duration: 0.3, options: UIViewAnimationOptions.curveEaseInOut, animations: nil, completion: nil)
PageVC currently changes pages by swiping, but I want to be able to navigate backward and forward through view controllers using two buttons
Add your buttons to page content, then disable horizontal scrolling on PageVC's scrollview or disable views' user interaction in a mannered fashion.
How Can I slide Views programmatically using buttons with existing UIPageViewController
First, PageViewController
instantiates a child controller which instantiates a PageViewController
.. Is that really a good idea? Then in your toFirstTapped
, you instantiate a FirstViewController
but do nothing with it..
If you do nothing with it, how do you expect it to work?
In any case, try the below:
protocol PageNavigationDelegate : class {
weak var pageController: PageViewController? { get set }
}
class PageViewController: UIPageViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.setViewControllers([getFirst()], direction: .forward, animated: true, completion: nil)
self.dataSource = self as UIPageViewControllerDataSource
}
}
extension PageViewController : UIPageViewControllerDataSource {
func getFirst() -> FirstViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
controller.pageController = self
return controller
}
func getSecond() -> SecondViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
controller.pageController = self
return controller
}
func getThird() -> ThirdViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
controller.pageController = self
return controller
}
@discardableResult
func goToPreviousPage() -> Bool {
let controller = self.viewControllers!.first!
if controller.isKind(of: SecondViewController.self) {
self.setViewControllers([getFirst()], direction: .reverse, animated: true, completion: nil)
return true
}
if controller.isKind(of: ThirdViewController.self) {
self.setViewControllers([getSecond()], direction: .reverse, animated: true, completion: nil)
return true
}
return false
}
@discardableResult
func goToNextPage() -> Bool {
let controller = self.viewControllers!.first!
if controller.isKind(of: FirstViewController.self) {
self.setViewControllers([getSecond()], direction: .forward, animated: true, completion: nil)
return true
}
if controller.isKind(of: SecondViewController.self) {
self.setViewControllers([getThird()], direction: .forward, animated: true, completion: nil)
return true
}
return false
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: SecondViewController.self) {
return getFirst()
}
if viewController.isKind(of: ThirdViewController.self) {
return getSecond()
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: FirstViewController.self) {
return getSecond()
}
if viewController.isKind(of: SecondViewController.self) {
return getThird()
}
return nil
}
}
class PageNavigationController : UIViewController, PageNavigationDelegate {
var pageController: PageViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func goToPreviousController(_ sender: Any) {
pageController?.goToPreviousPage()
}
@IBAction func goToNextController(_ sender: Any) {
pageController?.goToNextPage()
}
}
class FirstViewController: PageNavigationController {
}
class SecondViewController: PageNavigationController {
}
class ThirdViewController: PageNavigationController {
}
First we created a protocol. We made sure that all our PageController's sub-controllers will implement it. This way, they can navigate to previous and next pages..
Next, we create our extension which has the goToPreviousPage
and goToNextPage
function.. When we instantiate each controller page, we assign self
to its protocol implementation variable. That way, the controller can access the PageViewController
's methods..
Finally, in our First
, Second
, and Third
controllers, we just tell it to go forward or backward on button press.
Personally, I'd prefer to keep track of controllers in an array and just return those in my delegates.
Related Topics
Understanding UIviewrepresentable
Validatemenuitem or Menuwillopen Not Called for Nsmenu
Macos Remote Push Notifications Not Showing Alert Banner
Create Skspritenode with an Asset Programmatically
How to Set Window Level in Swift
Wkwebview on Macos Cuts Off Top
Disable Bringing App Window to Front. After Closing Another Window
Need Clarification on Anyobject in Swift
How to Find The Top 3 Maximum Values in a Swift Dictionary
Exc_Badinstruction When Computing a Hash Value
Given a Swift 'Any' Type How to Determine If It's an 'Optional'
Access Environment Variable Inside Global Function - Swiftui + Coredata
Populate a Multidimensional Array with a Loop
How to Create a UIprintpaper to Test UIprintinteractioncontrollerdelegate