Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: How sync two UIScrollview

I have two horizontal UIScrollviews. I want to synchronise their scrolling when user drag fingers in either of them. Here is my code:

self.topScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.topScrollView.delegate = self;
self.topScrollView.bounces = YES;

self.bottomScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.bottomScrollView.delegate = self;
self.bottomScrollView.bounces = YES;
...

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if (scrollView == self.topScrollView)
    {
        self.bottomScrollView.delegate = nil;
    }
    else
    {
        self.topScrollView.delegate = nil;
    }
    ...
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{   
    ...
    self.topScrollView.delegate = self;
    self.bottomScrollView.delegate = self;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    ...
    self.topScrollView.delegate = self;
    self.bottomScrollView.delegate = self;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // Sync the two scroll views
    if (scrollView == self.topScrollView)
    {
        [self.bottomScrollView setContentOffset:scrollView.contentOffset animated:NO];
    }
    else
    {
        [self.topScrollView setContentOffset:scrollView.contentOffset animated:NO];
    }
    ...
}

The two scroll views do scroll synchronously, however, the problem is all the bouncing and deceleration are gone. The whole scrolling movement becomes really rigid. If I remove all the syncing code, then each scroll view works just fine individually. So, what is the problem? Or can UIScrollView not be synchronised?

like image 217
crab oz Avatar asked May 22 '15 13:05

crab oz


Video Answer


2 Answers

You can use topScrollView.panGestureRecognizer and bottomScrollView.panGestureRecognizer to take both gesture recognizers and add them to a common superview enclosing both scroll views. Pan gestures on this superview would then be recognized by both children.

You'll most likely also need to be the delegate of both recognizers and let them be recognized simulaneously:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}
like image 80
jszumski Avatar answered Oct 30 '22 10:10

jszumski


I worked out the solution according to jszumski's answer. However, my situation is two vertical UIScrollViews side by side (scrollViewLeft and scrollViewRight). It should work for horizontal UIScrollViews without too much modification.

First, create a custom UIScrollView.

//.h file

@interface CSScrollView : UIScrollView

@end

//.m file

@implementation CSScrollView


-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{

    return YES;

}

@end

Secondly, in your mainview,

- (void)viewDidLoad {

    [super viewDidLoad];


    [self.view addGestureRecognizer:self.scrollViewLeft.panGestureRecognizer];

    [self.view addGestureRecognizer:self.scrollViewRight.panGestureRecognizer];

}

That's everything I need to set up two synchronized scrollviews. The real effect is much better than the regular way of sending/subscribing notifications in scrollview's scrollViewDidScroll and synchronize the contentOffset.

like image 22
Bo Yuan Avatar answered Oct 30 '22 10:10

Bo Yuan