Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

objective c - UIPageViewController automatic scrolling in iOS

I am making one app, in which PageViewController should scroll in some time interval. Currently I have done till manual scrolling. User can scroll any images and it will work. But stuck with achieve automatic scrolling with user touches. Below is my code. Please help me on this.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    _pageTitles = @[@"", @"", @"", @""];
    _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 - 50);

    [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)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];

    self.navigationController.navigationBar.hidden = YES;
}

#pragma mark - Page View Controller Data Source

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

    index--;
    return [self viewControllerAtIndex:index];
}

- (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];
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    return [self.pageTitles count];
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@Daniel your link is broken and your "answer" does little to explain your solution to the question. For those interested in reading documentation for the UIPageViewController Class.

The method to pay attention to here is :

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

The UIPageViewController expects you to tell it what data to deliver and what controller to use based on a value. Here I am telling my UIPageController Subclass to be the delegate and dataSouce. After configuring the delegate methods and the viewControllerAtIndex dataSource method, I added a custom interval which calls my loadNextController method. In that method I am checking to see if the "next" controller is nil. If it is not nil I pass the "next" controller as the @[starting controller] back to a second call to setViewControllers. If it is nil I just reset the index value to ZERO and call setViewControllers with my "next" controller as the @[starting controller]. This custom subclass serves to page to the next or first controller automatically. The bonus is that user interaction is still handled by the UIPageViewController Class.

Note: The initial call to setViewControllers is required because your UIPageViewContrller will not know what if any viewController can be loaded first. My second call to setViewControllers does nothing more than skip to the next or first viewController.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.index = 0;
    self.delegate = self;
    self.dataSource = self;

    /*! setup an interval */
    [NSTimer scheduledTimerWithTimeInterval:10.0
                                     target:self
                                   selector:@selector(loadNextController)
                                   userInfo:nil
                                    repeats:YES];

    /*! set starting controller */
    NSArray *startingViewControllers = @[[self  viewControllerAtIndex:self.index]];

    [self setViewControllers: startingViewControllers
                   direction: UIPageViewControllerNavigationDirectionForward
                    animated: YES
                  completion: nil];
}

- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    NSUInteger index = ((YSPageContentViewController*) viewController).pageIndex;
    if (index > 0 ) {
        return [self viewControllerAtIndex:index-1];
    }
    return nil;
}

- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    NSUInteger index = ((YSPageContentViewController*) viewController).pageIndex;
    if (index+1 < [self.items count] ) {
        return [self viewControllerAtIndex:index+1];
    }
    return nil;
}

- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index{
    if (index < [self.items count]) {
        PageContentViewController *pageContentViewController =   [[PageContentViewController alloc]init];
        pageContentViewController.pageIndex = index;
        pageContentViewController.image = (UIImage*)self.items[index];
        return pageContentViewController;
    }
    return nil;
}

/*! set next controller */
- (void)loadNextController {
    PageContentViewController *nextViewController = [self viewControllerAtIndex:self.index++];
    if (nextViewController == nil) {
        self.index = 0;
        nextViewController = [self viewControllerAtIndex:self.index];
    }
    [self setViewControllers:@[nextViewController]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:YES
                  completion:nil];
} 

Note: This does work; however I am not always returning the correct controller when the internal gesture recognizer changes the controller. Somewhere along the way I am losing track of the index. I will update this with my finished implementation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...