5

I have a question about infinite paging in a ScrollView. In my app I have only 3 subviews in ScrollView. Each subview is loaded from xib file. Normally it looks like ABC in ScrollView. I wanted to make infinite paging so I added end caps and now it looks like CABCA. If the user is on the first C, it jumps to regular C and if user is on the last A, it jumps to regular A. Here is a code:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender {

  if (scrollView.contentOffset.x == 0)
  {
      [scrollView scrollRectToVisible:CGRectMake
      ((scrollView.frame.size.width * 3), 0,
      scrollView.frame.size.width,
      scrollView.frame.size.height) animated:NO];
  } 
  else if (scrollView.contentOffset.x == scrollView.frame.size.width * 4)
  {
     [scrollView scrollRectToVisible:CGRectMake
     (scrollView.frame.size.width, 0,
      scrollView.frame.size.width,
      scrollView.frame.size.height) animated:NO];
   }
}

It works perfectly now. But I have ViewController for each subview and this is how I am adding them to ScrollView:

  subViewController1 = [[SubViewController1 alloc] initWithNibName:@"SubView" bundle:nil];
  subViewController1.view.frame =
    CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height);
  [scrollView addSubview:subViewController1.view];

Problem is that there is one duplicate of A and C view so now I have 5 controllers instead of 3. And If I want to add something into a A view, I have to add it also into duplicate of A view.

Is there a way how to control view A and duplicate of A with one controller so I don't have to create two instances of one controller? Thank you.

chandan
  • 2,453
  • 23
  • 31
DanielH
  • 953
  • 10
  • 30

1 Answers1

15

Better still, you don't need to have duplicate view A's and duplicate view C's, you just move them around in - (void)scrollViewDidScroll:(UIScrollView *)scrollView while manipulating the contentOffset.

Setup: probably very similar to how you already do it.

Set your UIScrollView to have contentSize 3 times it's bounds width. Make sure paging is turned on and bouncing off.

Add your ABC subviews to the UIScrollView from left to right.

Also have an array in your ViewController called _contentViews that contains your UIViews ABC.

Then implement this which will reset the content offset and move your subviews around at the same time when the scrollview reaches the edges:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {

    if(scrollView.contentOffset.x == 0) {
        CGPoint newOffset = CGPointMake(scrollView.bounds.size.width+scrollView.contentOffset.x, scrollView.contentOffset.y);
        [scrollView setContentOffset:newOffset];
        [self rotateViewsRight];
    }
    else if(scrollView.contentOffset.x == scrollView.bounds.size.width*2) {
        CGPoint newOffset = CGPointMake(scrollView.contentOffset.x-scrollView.bounds.size.width, scrollView.contentOffset.y);
        [scrollView setContentOffset:newOffset];
        [self rotateViewsLeft];
    }
}

-(void)rotateViewsRight {
    UIView *endView = [_contentViews lastObject];
    [_contentViews removeLastObject];
    [_contentViews insertObject:endView atIndex:0];
    [self setContentViewFrames];

}

-(void)rotateViewsLeft {
    UIView *endView = _contentViews[0];
    [_contentViews removeObjectAtIndex:0];
    [_contentViews addObject:endView];
    [self setContentViewFrames];

}

-(void) setContentViewFrames {
    for(int i = 0; i < 3; i++) {
        UIView * view = _contentViews[i];
        [view setFrame:CGRectMake(self.view.bounds.size.width*i, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
    }
}
Mike Pollard
  • 10,195
  • 2
  • 37
  • 46
  • 1
    Thank you! That is great! But there was a problem: when the app starts, view A is shown and you can scroll to the view B but you can´t scroll to the view C bcause this view is in the beginning of scrollview and scrollViewDidScroll isn´t fired when scrolling to the right. So I set views in this order CAB and view A is shown when app starts so you can scroll in both ways... – DanielH May 28 '13 at 12:01
  • Yep, I thought I'd leave that little 'feature' in for you to fix ;) – Mike Pollard May 28 '13 at 12:12
  • 1
    You can also replace the "equals" check by smaller than or greater than: `if(scrollView.contentOffset.x < 0) {` and `else if(scrollView.contentOffset.x > scrollView.bounds.size.width*2) {`, so the scrollview doesn't have to halt first before the views change position. That also fixes the problem DanielH had in the first comment. – Huby Apr 07 '16 at 08:19