I have a series of VCs in a PageViewController that a user navigates left to right through with their fingers. I need to add in buttons that essentially perform the same action as the finger swiping, moving left or right by one through the VCs . How can I do this? Right now I am using these two methods to dynamically setting the VCs as the user swipes:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;
Is there someway I can do the same thing if a user clicks a button?
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];
}
In case Pages can be navigated by added button (Previous, Next) & also by swipe with page control ON.
Please go through below:
//Set Delegate & Data Source for PageView controller [Say in View Did Load]
self.pageViewController.dataSource = self;
self.pageViewController.delegate = self;
// PageBefore & After When User Scroll to move next or previous page
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
[_nextBtn setTitle:#"Next" forState:UIControlStateNormal];
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if (index == NSNotFound)
{
return nil;
}
if (index > 0)
{
index--;
}
else
{
return nil;
}
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if (index == NSNotFound) {
return nil;
}
if (index < 3)
{
index++;
}else
{
return nil;
}
return [self viewControllerAtIndex:index];}
//To Match Exact Index page view when scrolled & navigated using button action. Place button index when page is been translated.
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
buttonIndex = (int)((PageContentViewController*) pendingViewControllers.firstObject).pageIndex;}
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if (buttonIndex == 0)
{
_backButton.hidden = true;
}else if (buttonIndex == [self.pageImages count] - 1)
{
_backButton.hidden = false;
[_nextBtn setTitle:#"Begin" forState:UIControlStateNormal];
}else
{
_backButton.hidden = false;
}
}
//Previous , Next Button Actions
-(void)backBtnClicked:(id)sender{
if (buttonIndex > 0)
{
buttonIndex -= 1;
}
if (buttonIndex < 1) {
_backButton.hidden = YES;
}
if (buttonIndex >=0) {
[_nextBtn setTitle:#"Next" forState:UIControlStateNormal];
PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}}
-(void)nextBtnAction:(id)sender{
if (buttonIndex < 3)
{
buttonIndex += 1;
}
if(buttonIndex == _pageImages.count){
//Navigate Outside Pageview controller
} else{
if (buttonIndex ==3) {
[_nextBtn setTitle:#"Begin" forState:UIControlStateNormal];
}
_backButton.hidden = NO;
PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}}
//BUTTON INDEX
-(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{
return [self.pageImages count];}
-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{
return buttonIndex;}
Related
I have been unable to find a solution to this issue that resolves my case. I am looking to call the two blocks of code that swipe my page view controller programmatically.
Such as a [self viewControllerAfterViewController:self] that would call the last block of code.
In viewDidLoad
[super viewDidLoad];
indexvalue = 1;
NSLog(#"main intitated");
// Do any additional setup after loading the view, typically from a nib.
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
ViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:#"Main"];
Request *pvc;
viewcontrollers =[NSArray arrayWithObjects:tvc, pvc, nil];
[self.pageViewController setViewControllers:viewcontrollers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self addChildViewController:pageViewController];
[self.view addSubview:pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
Code to swipe between screens called by swipe gesture
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSLog([NSString stringWithFormat:#"%i", indexvalue]);
if (indexvalue == 0 & check0 < 1) {
check0 = 1;
ViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:#"Main"];
indexvalue = 1;
return tvc;
}
else {
return nil;
}
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSLog([NSString stringWithFormat:#"%i", indexvalue]);
if (indexvalue == 1 & check1 < 1) {
check1 = 1;
Request *pvc = [self.storyboard instantiateViewControllerWithIdentifier:#"Friends"];
indexvalue = 0 ;
return pvc;
}
else {
return nil;
}
}
viewcontrollers =[NSArray arrayWithObjects:tvc, pvc, nil];
replace with
viewControllers = #[tvc];
viewControllers= [self viewControllerAtIndex:0];
Now add this method
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) {
return nil;
}
if (index == 0) {
//first view
ViewController *pageContentViewController2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
return pageContentViewController2;
}
//second view
Request *pageContentViewController3 = [self.storyboard instantiateViewControllerWithIdentifier:#"Request"];
return pageContentViewController3;
}
I am using the following code for implementing UIPageViewController. How to move next and previous page using UIButton click event?
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentView*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentView *) viewController).pageIndex;
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [arrCarStatus count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
You need to call UIPageViewController methods on your UIButton tap. Here is what you need to do. Create a method for UIPageViewController
- (void)changePage:(UIPageViewControllerNavigationDirection)direction {
NSUInteger pageIndex = ((ViewControllerContainingUIImageView *) [_pageViewController.viewControllers objectAtIndex:0]).index;
if (direction == UIPageViewControllerNavigationDirectionForward)
{
pageIndex++;
}
else
{
pageIndex--;
}
initialViewController = [self viewControllerAtIndex:pageIndex];
if (initialViewController == nil) {
return;
}
[_pageViewController setViewControllers:#[initialViewController]
direction:direction
animated:YES
completion:nil];
}
Now call this method on UIButton click providing direction forward/back
-(void)backSlide
{
[self changePage:UIPageViewControllerNavigationDirectionReverse];
}
-(void)forwardSlide
{
[self changePage:UIPageViewControllerNavigationDirectionForward];
}
- (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];
}
Try This It May Help you. I Have Made totally New Demo.
you can just use the delegate Methods of page view controller named as a
- (void)changePage:(UIPageViewControllerNavigationDirection)direction
and just simple check the condition which i mention below.
if (direction == UIPageViewControllerNavigationDirectionForward)
{
pageIndex++;
}
else
{
pageIndex--;
}
I'm trying to add a UIPageViewController to my App using following code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *viewControllers = #[page0,
page1,
page2];
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
self.pageController.dataSource = self;
self.pageController.view.frame = self.view.frame;
[self.pageController setViewControllers:#[[viewControllers firstObject]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self.pageController willMoveToParentViewController:self];
[self addChildViewController:self.pageController];
[self.view addSubview:self.pageController.view];
[self.pageController didMoveToParentViewController:self];
}
Then problem is that when I run the application, using the Simulator or a physical device, I get a empty screen. If I try to swipe the views I can see that the page that I actually added to the viewControllers array is already there but outside of the screen. Making some debugging with SparkInspector, I can see that the view is actually there but with an offset with the same value equal to the screen width.
I also have implemented the DataSource for the UIPageViewController. Here are the implementation of the delegated methods:
- (NSInteger) presentationCountForPageViewController:(UIPageViewController *)pageViewController {
return 3;
}
- (NSInteger) presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
return 0;
}
- (UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
if (viewController == nil) {
return [viewControllers firstObject];
}
NSUInteger index = [viewControllers indexOfObject:viewController];
// NSParameterAssert(index != NSNotFound);
index++;
if (index == viewControllers.count) {
return nil;
}
return [viewControllers objectAtIndex:index];
}
- (UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (viewController == nil) {
return [viewControllers firstObject];
}
NSUInteger index = [viewControllers indexOfObject:viewController];
if (index == 0) {
return nil;
}
index--;
return [viewControllers objectAtIndex:index];
}
I cannot see why the App is offsetting the view controllers, so any advice will be very helpful.
I need a dynamic UIPageViewController, the number of pages depends on the quantity of items of my array.
I have two views for this. One for the first page and another one for the other pages. It will be always more than 2 pages (two items on my array).
I'm trying to test with fixed values. But the paging it's not right. The index is not correct.
1st problem, the presentationCountForPageViewController [_vc count] returns nil;
2nd problem, the pagination it's not right. I get to the last page, and the first view it's gone, so if I go back, goes to second view, always...
Please, help!
- (void)viewDidLoad {
[super viewDidLoad];
FirstViewController *agenda = (FirstViewController*)[self viewControllerAtIndex:0];
[_vc addObject:#"FirstViewController"];
[_vc addObject:#"SecondViewController"];
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
NSArray *viewControllers = [NSArray arrayWithObject:agenda];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
UIPageControl *pageControlAppearance = [UIPageControl appearanceWhenContainedIn:[UIPageViewController class], nil];
pageControlAppearance.pageIndicatorTintColor = [UIColor lightGrayColor];
pageControlAppearance.currentPageIndicatorTintColor = [UIColor darkGrayColor];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [_vc indexOfObject:viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
//notice here I call my instantiation method again essentially duplicating work I have already done!
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = [_vc indexOfObject:viewController];
if (index == NSNotFound) {
return nil;
}
index++;
return [self viewControllerAtIndex:index];
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (index == 0){
FirstViewController *firstController = [self.storyboard instantiateViewControllerWithIdentifier:#"FirstViewController"];
return firstController;
}
else{
SecondViewController *secondController = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
return secondController;
}
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [_vc count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
As per comments/chat, a few things needed resolving:
You need to instantiate the _vc array
You need to add UIViewControllerobjects to this array, not the strings you currently use
You need to amend the viewControllerBeforeViewController and viewControllerAfterViewController methods to return the relevant element from the _vc array, remembering to test that the index remains within the array's bounds, to prevent swiping beyond the final page, or before the first (agenda) page.
I am trying to build a app based on information displaying via pageviewcontroller.
To prevent boredom, i would like to display the pages randomly. Everytime open up the app at different page. How can i do that, below is the code i am using. Thanks
_pageTitles = #[#"Over 200 Tips and Tricks", #"Discover Hidden Features", #"Bookmark Favorite Tip", #"Free Regular Update"];
_pageImages = #[#"page1.png", #"page2.png", #"page3.png", #"page4.png"];
// Create page view controller
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
PageContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) {
return nil;
}
// Create a new view controller and pass suitable data.
PageContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
pageContentViewController.imageFile = self.pageImages[index];
pageContentViewController.titleText = self.pageTitles[index];
pageContentViewController.pageIndex = index;
return pageContentViewController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.pageTitles count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [self.pageTitles count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
generate your datasources, _pageTitles and _pageImages, at startup new with a random number so that the entries each run have another array index. you could do that in viewDidLoad.