views:

346

answers:

2

Setup: I have a UITableView, each UITableViewCell has a UIScrollView. What I am trying to do is to get all of the UIScrollViews to scroll together, such that when you scroll one of them all of the UIScrollViews appear to scroll simultaneously.

What I've done is subclass UITableView so that it has an array of all of the UIScrollViews within its table cells. I then forwarded TouchesBegan, TouchesMoved, TouchesCancelled, and TouchesEnded from the UITableView to all of the UIScrollViews in the array.

This doesn't appear to work. The UIScrollViews do not scroll! The only way I've managed to get this to work is to call the setContentOffset: method on the scrollviews. However, this is a pretty bad solution since it doesn't give you the swiping and deceleration features of the UIScrollView.

Any ideas on why my touches methods aren't getting to the UIScrollViews? Or a better way to implement this?

A: 

Hi

I did something "similar" where I had 4 scrollViews incased inside a parent view. I placed a scrollView inside a UIView, this UIView was passed a delegate from its parentView, that was the view who kept track of all the scrollViews. The UIView containing a scrollVIew implemented the UIScrollViewDelegate and this method;

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

[self.delegate scrolling:[self.scrollView contentOffSet]];

}

Now the parent view did this on all the scrollViews:

- (void) scrolling:(CGFloat) offset {

    for(UIScrollView *s in self) {
        [s setContentOffset:offset animated:YES];
    }
}

It is of course a bit of a strain on the CPU, but scrolling several views will be that under any circumstances :/

Hope this was something in the direction of what you needed, and that it made any sense.

Added:

I took me 8 different paths and a lot of mass chaos before I made it work. I dropped the touchedBegan approach early, there is just no way to write something that comes close to Apples swipe, flick, scroll algorithms.

I don't know if the tableview and scrollview will "steal" each others touch events, but as I can read from your description you made that part work.

A follow up idea to ease the CPU usage. add each scrollview to a cell, set its tag=14, now when scrolling asked for all visible cells only, ask for viewWithTag=14, set the contentOffset on this. Save the content offset globally so you can assign it to cells being scrolled onto the screen in cellForRowAtIndexPath.

So set the offSet to a global property, in cellForRowAtIndexPath find the view with tag = 14, set its offset. This way you don't even need a reference to the scrollViews only the delegate.

RickiG
ah interesting solution. I will try this once I get home. I didn't think of using setContentOffset based on the scrollViewDidScroll, I did it based on the touches. As you can imagine settings animated:YES for each touch caused mass chaos.
Ricki, great suggestions, going to try it out tonight. Thanks!!
A: 

Ok, got it working. Thanks for the tips Ricki!

2 things to add to Ricki's solution, if you want to avoid an infinite loop, you have to check to see whether the scrollView's tracking or dragged properties are set. This will insure that only the ScrollView that is actually being dragged is calling the delegate.

- (void)scrollViewDidScroll:(UIScrollView *) theScrollView { 
         if (theScrollView.dragging || theScrollView.tracking) 
              [self.delegate scrolling:[theScrollView contentOffSet]]; 
}

Also, in the scrolling method of the delegate, I set animated to NO, this got rid of the delay between the initial swipe and the other scrollviews getting updated.

You are welcome, great that you worked out the kinks so fast:)My initial challenge was a bit different from yours but nice to hear that the solution was applicable in other designs as well.
RickiG