0
votes

I have a UIViewController in my app with a navigation bar as shown in the below gif. The UIViewController contains a UIPageViewController with 4 pages. Each tab on the navigation bar represents one page from the UIPageViewController.

enter image description here

I am trying to implement a smooth scrolling between these UIPageViewController pages i.e if I am currently on the first tab and I click on the last tab on the navigation bar, the UIPageViewController must smoothly scroll through all the tabs to the last one. Though this works right now, I am not happy with the scroll performance as it looks jittery. I am using the

- setViewControllers:direction:animated:completion: api to scroll between the pages.

This is what my code looks like

- (void)navigateToNextPage {

    //you have navigated to the destination, return
    if(self.destinationPageIndex == self.currentPageIndex)
        return;

    if(self.destinationPageIndex < 0 || self.destinationPageIndex >= [self.pageViewControllerIdentifiers count])
        return;

    //determine the scroll direction
    UIPageViewControllerNavigationDirection direction = self.destinationPageIndex < self.currentPageIndex ? UIPageViewControllerNavigationDirectionReverse : UIPageViewControllerNavigationDirectionForward;

    //get the index of the next page to scroll  to
    NSInteger nextPageIndex = self.destinationPageIndex < self.currentPageIndex ? self.currentPageIndex-1 : self.currentPageIndex+1;

    //get the storyboard identifier of the page to navigate to
    NSString *identifier = [self.pageViewControllerIdentifiers objectAtIndex:nextPageIndex];
    NSString *storyboardName = @"Sales";
    id viewController = [COSCheckoutNavigationViewController instantiateControllerFromStoryboardName:storyboardName storyboardIdentifier:identifier];
    NSArray *viewControllers = @[viewController];

    __weak typeof (self) weakSelf = self;
    [self.pageViewController setViewControllers:viewControllers direction:direction animated:YES completion:^(BOOL finished) {
        [weakSelf updateCurrentPageIndex];

        //navigate to the next page after small delay
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf navigateToNextPage];
        });
    }];
}

Is there a way I could improve upon this code for better scroll performance? Would any other technique help me achieve what I'm trying?

2
hello @tbag can you please help me , I'm stacked in pageViewController , I want to change my custom tabViews color change when pageviewcontroller scroll to next page or pervious page .Subhash Sharma

2 Answers

0
votes

Swift 3.0.2

I faced the same problem as you and I found a solution that works for me. Bear in mind that I manage the childViewControllers with a UISegmentedControl. Right now, I'm not allowing the swiping gesture because it messes up my views. This recursive call allows for the animation between every UIViewController inside a UIPageViewController.

// We call this method recursively until we find our desired view controller
// We do it this way to provide an animated transition if you find yourself in
// the first view and want to go to the last one. If we just jumped to the
// desired VC, we will not se any animation between the different VCs in the
// middle and it would look like there are only two VCs
func segmentedControl(index: Int) {
    let desiredVC = pages[index]
    if pages[currentIndex] != desiredVC {
        if index > currentIndex {
            self.setViewControllers([pages[currentIndex+1]], direction: .forward, animated: true, completion: nil)
            currentIndex += 1
        } else {
            self.setViewControllers([pages[currentIndex-1]], direction: .reverse, animated: true, completion: nil)
            currentIndex -= 1
        }
        segmentedControl(index: index)
    }
}

My UISegmentedControl just sends the selected index to this method.

-1
votes

I dont know about your solution but may be it will help you.

Pageviewcontroller