Cross Directional Uiscrollviews - How to Modify the Scrolling Behaviour

Cross Directional UIScrollViews - Can I Modify the Scrolling Behaviour?

According to my understanding of the question, it is only while the tableView is scrolling we want to change the default behaviour. All the other behaviour will be the same.

SubClass UITableView. UITableViews are subClass of UIScrollViews. On the UITableView subClass implement one UIScrollView's UIGestureRecognizer's delegate method

- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer
{
//Edit 1
//return self.isDecelerating;
//return self.isDecelerating | self.bounces; //If we want to simultaneous gesture on bounce and scrolling
//Edit 2
return self.isDecelerating || self.contentOffset.y < 0 || self.contentOffset.y > MAX(0, self.contentSize.height - self.bounds.size.height); // @Jordan edited - we don't need to always enable simultaneous gesture for bounce enabled tableViews
}

As we only want to change the default gesture behaviour while the tableView is decelerating.

Now change all 'UITableView's class to your newly created tableViewSubClass and run the project, swipe should work while tableView is scrolling. :]

But the swipe looks a little too sensitive while tableView is scrolling. Let's make the swipe a little restrictive.

SubClass UIScrollView. On the UIScrollView subclass implement another UIGestureRecognizer's delegate method gestureRecognizerShouldBegin:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
CGPoint velocity = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:self];
if (abs(velocity.y) * 2 < abs(velocity.x)) {
return YES;
}
}
return NO;
}

We want to make the "swipe is clearly horizontal". Above code only permits gesture begin if the gesture velocity on x axis is double than on y axis. [Feel free to increase the hard coded value "2" if your like. The higher the value the swipe needs to be more horizontal.]

Now change the `UiScrollView' class (which has multiple TableViews) to your ScrollViewSubClass. Run the project. :]

Sample Image

I've made a project on gitHub https://github.com/rishi420/SwipeWhileScroll

Nested UIScrollViews scrolling simultaneously

The glitchy behavior was happening when the views were dragged out of the content area, released, and then tapped/dragged again before the scroll views bounced back. This could happen, for example, when the view was scrolled by several small swipes. One of the scroll views would get confused and try to decelerate (bounce) while simultaneously being dragged, causing it to jitter back and forth between the origin and where it had been dragged to.

I was able to fix this by reversing the nesting of the scroll views (paging view inside of the vertical scrolling view) and by adding the delegate to the paging view's UIPanGestureRecognizer instead of to the scrolling view's gesture. Now it scrolls naturally as if it was a single scroll view while still conforming to paging only in the horizontal direction. I don't think it was intended for scroll views to be tricked into scrolling simultaneously like this, so I'm not sure if the original glitchy behavior was the result of a bug, or just a consequence of doing something unintended.

UIScrollView Odd Scrolling

The problem was that I was using a Freeform UIViewController of 1800 x 600 - so I could layout my content in interface builder (3 pages). Reverting back to 600 x 600 restores the normal scrolling. I don't know why this should happen since the whole point of autolayout is to not be affected to these changes in size and my view controller is totally adaptive...but there we are.

This is the approach I'm using: UIScrollView Paging Autolayout & Storyboard - its very useful, but be aware to restore your view controllers to a reasonable size before you compile otherwise you get odd scrolling!

Making two UIScrollViews follow each others scrolling

Set the delegate of scroll view A to be your view controller... then have...

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollViewB.contentOffset;
offset.y = scrollViewA.contentOffset.y;
[scrollViewB setContentOffset:offset];
}

If you want both to follow each other, then set delegate for both of them and use...

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if([scrollView isEqual:scrollViewA]) {
CGPoint offset = scrollViewB.contentOffset;
offset.y = scrollViewA.contentOffset.y;
[scrollViewB setContentOffset:offset];
} else {
CGPoint offset = scrollViewA.contentOffset;
offset.y = scrollViewB.contentOffset.y;
[scrollViewA setContentOffset:offset];
}
}

The above can be refactored to have a method which takes in two scrollviews and matches one to the other.

- (void)matchScrollView:(UIScrollView *)first toScrollView:(UIScrollView *)second {
CGPoint offset = first.contentOffset;
offset.y = second.contentOffset.y;
[first setContentOffset:offset];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if([scrollView isEqual:scrollViewA]) {
[self matchScrollView:scrollViewB toScrollView:scrollViewA];
} else {
[self matchScrollView:scrollViewA toScrollView:scrollViewB];
}
}

Swift 3 Version:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == scrollViewA {
self.synchronizeScrollView(scrollViewB, toScrollView: scrollViewA)
}
else if scrollView == scrollViewB {
self.synchronizeScrollView(scrollViewA, toScrollView: scrollViewB)
}
}

func synchronizeScrollView(_ scrollViewToScroll: UIScrollView, toScrollView scrolledView: UIScrollView) {
var offset = scrollViewToScroll.contentOffset
offset.y = scrolledView.contentOffset.y

scrollViewToScroll.setContentOffset(offset, animated: false)
}

Passthrough touches of 2 UIScrollViews

As I understood, you want touches to be intercepted by UITableView as well as UICollectionView?

I think You can try resending touch events from your UICollectionView to UITableView.
(manually calling touchesBegin, touchesMoved, touchesEnded, etc.)

Maybe overriding touchesBegan, touchesMoved, touchesEnded methods will work for your case.

You can try overriding UICollectionView with your subclass (with property set to your UITableView instance) and implementing touch handling methods with something like this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
if (CGRectContainsPoint(self.tableView.frame, [touch locationInView:self.tableView.superview]) {
[self.tableView touchesBegan:touches withEvent:event];
}
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];

[self.tableView touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];

[self.tableView touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];

[self.tableView touchesCancelled:touches withEvent:event];
}

Hope it will help, however I'm not 100% sure about it.

I've found this article also, maybe it will be useful

http://atastypixel.com/blog/a-trick-for-capturing-all-touch-input-for-the-duration-of-a-touch/

Can't scroll up/down and scroll left/right at the same time on UITableView within a UIScrollView

Sample Image

Here's an example project that works:
https://github.com/rishi420/SwipeWhileScroll

You can read more about this topic here:

Cross Directional UIScrollViews - Can I Modify the Scrolling Behaviour?



Related Topics



Leave a reply



Submit