Search code examples
iphoneiosuiscrollviewuicollectionviewuiscrollviewdelegate

Manually scrolling two UICollectionViews showing the same content


As the title suggest, I have a UIViewController with two UICollectionViews which are displaying the same content in a horizontal fashion. The main one shows one photo at a time, the thumbs one shows several.

I have overridden the UIScrollViewDelegate method and added some code so that when the user scrolls the main CV, then the thumbs CV scrolls too. However I would like to enable the opposite as well (scroll the thumbs which will quickly move the main). However i'm getting a feedback effect.

Here is my code snippet:

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if(scrollView == self.mainCollectionView){
        CGFloat x = self.mainCollectionView.contentOffset.x / self.mainCollectionView.bounds.size.width * SM_IPHONE_THUMB_CONTAINER_SIZE; // cell width + spacing 48 + 8
        CGFloat y = 0;
        CGPoint contentOffset = CGPointMake(x, y);
        self.thumbsCollectionView.contentOffset = contentOffset;

    }
    else if(scrollView == self.thumbsCollectionView){
//        CGFloat   x = self.thumbsCollectionView.contentOffset.x / self.thumbsCollectionView.bounds.size.width * SM_IPHONE_THUMB_CONTAINER_SIZE; // cell width + spacing 48 + 8
//        CGFloat y = 0;
//        CGPoint contentOffset = CGPointMake(x, y);
//        self.mainCollectionView.contentOffset = contentOffset;

    }
}

I imagine that I can track touch down/up events to mask out what's allowed to happen, but before I attempt that I thought I'd see if there is a different way to do this? I am I overlooking a provided method that will help me out here?

Thanks.

Edit: solution. There was a UIScrollViewDelegate method that provided what I needed to track which layout was being touched. Updated code:

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if(scrollView == self.mainCollectionView &&
       self.scrollingView == self.mainCollectionView){
        CGFloat x = self.mainCollectionView.contentOffset.x / self.mainCollectionView.bounds.size.width * SM_IPHONE_THUMB_CONTAINER_SIZE; // cell width + spacing 48 + 8
        CGFloat y = 0;
        CGPoint contentOffset = CGPointMake(x, y);
        self.thumbsCollectionView.contentOffset = contentOffset;

    }
    else if(scrollView == self.thumbsCollectionView &&
            self.scrollingView == self.thumbsCollectionView){
        CGFloat x = self.thumbsCollectionView.contentOffset.x / SM_IPHONE_THUMB_CONTAINER_SIZE * self.mainCollectionView.frame.size.width; // cell width + spacing 48 + 8
        CGFloat y = 0;
        CGPoint contentOffset = CGPointMake(x, y);
        self.mainCollectionView.contentOffset = contentOffset;

    }
}


-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    self.scrollingView = scrollView;
}

Solution

  • Keep track of the currently dragging scroll view when scrollViewWillBeginDragging: is called.

    In scrollViewDidScroll:, update the scroll view that is not dragging:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        if(scrollView == self.mainCollectionView 
                 && self.mainCollectionView == self.scrollingView){ // new check
            CGFloat x = self.mainCollectionView.contentOffset.x / self.mainCollectionView.bounds.size.width * SM_IPHONE_THUMB_CONTAINER_SIZE; // cell width + spacing 48 + 8
            CGFloat y = 0;
            CGPoint contentOffset = CGPointMake(x, y);
            self.thumbsCollectionView.contentOffset = contentOffset;
    
        }
        else if(scrollView == self.thumbsCollectionView 
               && self.thumbsCollectionView== self.scrollingView){ // new check
            CGFloat   x = self.thumbsCollectionView.contentOffset.x / self.thumbsCollectionView.bounds.size.width * SM_IPHONE_THUMB_CONTAINER_SIZE; // cell width + spacing 48 + 8
            CGFloat y = 0;
            CGPoint contentOffset = CGPointMake(x, y);
            self.mainCollectionView.contentOffset = contentOffset;
    
    }