Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

2nd Update Thanks to @Segev's comment and reference to another topic, I was able to improve my demo to get it to basically do what I wanted. However, it is still not as smooth as Instagram's implementation, and I was wondering if anyone know how I could improve it to be smoother? Also, I noticed that sometimes (in my demo), when I'm swiping left/right very fast and I want to switch to swiping up/down, it will still continue to swipe left/right until I stop the swiping and let it stop first.

Update: I was able to get the table view to swipe left/right after stopping scrolling up/down by inheriting from UIScrollView and implementing the shouldRecognizeSimultaneouslyWithGestureRecognizer and shouldBeRequiredToFailByGestureRecognizer methods from UIGestureRecognizerDelegate. My idea was to return true in shouldRecognizeSimultaneouslyWithGestureRecognizer if the user is scrolling up/down the tableView, and then in shouldBeRequiredToFailByGestureRecognizer to fail the table view's up/down gesture.

But I am still unable to figure out how to let the user scroll up/down or left/right after stopping the initial up/down scroll (and the user's finger is still on the device).

I created a sample project here https://github.com/paulsfds/TableViewsInScrollView. You can test this by swiping down on the table view once, then lift your finger off and while it's still scrolling, put your finger back on to stop the scrolling. While your finger is still on the table view, try swiping left/right and it should work. But with this implementation if you try to swipe down the table view multiple times, it will sometimes get stuck because it will think that you are trying to swipe left/right. Any ideas?

Original: I have a couple UITableViews that are within a UIScrollView that has paging enabled, and is setup to let me page left and right so that only one UITableView is visible at a time. Here is a diagram (taken from Conflictive scroll on UITableView within UIScrollView)

                                 +--visible area--+  ---+
+---------`UIScrollView`---------+---------------+|  --+|
| +-------------+ +-------------+|+-------------+||  -+||
| |      0      | |      1      |||      2      |||   |||
| |`UITableView`| |`UITableView`|||`UITableView`|||  equal height
| |             | |             |||             |||   |||
| +-------------+ +-------------+|+-------------+||  -+||
+--------------------------------+---------------+|  --+| 
                                 +----------------+  ---+

What I would like to achieve is if the user scrolls down the table view, and then lifts their finger off (and the scrolling down animation is still happening), the user can chose to swipe left and right to go to the next table view. Right now if the user scrolls down the table view, and then lifts their finger off and while the scrolling down animation is still happening, and then puts their finger back on to swipe left and right, it will not allow the user to scroll left and right, and I am stuck viewing the already visible table view unless I wait for the table view scrolling to stop completely and then swipe left and right.

TL;DR Basically I cannot scroll up/down the table and swipe left/right in the scroll view at the same time, but I would like to be able to do this. An example of this would be in the iOS Instagram app on the Activity tab. You can scroll down and then swipe right while the table view is still scrolling.

like image 951
d0nutz1 Avatar asked Jun 23 '15 18:06

d0nutz1


4 Answers

enter image description here

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?

like image 100
Segev Avatar answered Nov 17 '22 13:11

Segev


Unfortunately Apple does not support embedding UITableViews inside UIScrollViews:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebView_Class/index.html

IMPORTANT

You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.

However with that said, it still may be possible to achieve what you're looking for. Have you tried setting delayContentTouches to true so that the scrollview sends its failed scrolled-gesture (i.e. the horizontal scroll) to its children (i.e. your tableview)?

self.yourScrollView.panGestureRecognizer.delaysTouchesBegan = true
like image 43
Oren Avatar answered Nov 17 '22 13:11

Oren


While this question has an accepted answer, I wanted to provide my own solution for others who may have similar problems:

Use a UICollectionView to page the UITableViews instead of UIScrollView

Basic steps using UIStoryboards:

  • Add a UICollectionView to UIViewController in the Storyboard.
  • Update the UICollectionView's attributes so that you are using paging instead of scrolling, and set the layout attributes so that the cell takes up the full size of the UICollecionView.
  • Add a UITableView to the UICollectionViewCell.
  • Add the IBOulet for the UICollectionView to your ViewController.h and connect the outlet.
  • Create a UICollectionViewCell subclass, and add the IBOutlet to the UITableView to the cell's .h
  • In your Storyboard, set the Class type of the UICollectionViewCell to the custom cell you just created.
  • Connect the IBOutlets for your UICollectionView and UITableView.
  • Lastly, you will need to set your delegates and datasources for the two, and implement the methods. Since I tried this as a quick example, I made my ViewController the delegate and datasource for both the UICollectionView and UITableView. However, your implementation may differ from here.

As long as your configure your UICollectionView's datasource properly it should page just fine.

like image 30
Aron C Avatar answered Nov 17 '22 12:11

Aron C


I've just done something with a similar functionality.

What worked out for me was to make an extension for the UIPanGestureRecognizer (I'm working with swift 2; if you want I could rewrite the solution for objC) so I can know when the user got the finger out of the device. Then you can able to swipe left/right I suppose.

Here is the code, I explain it below:

extension UIPanGestureRecognizer {

public override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent) {
    state = .Ended
    NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "panningEnded", object: nil))
}

}

This is the only way I could reach the touchesEnded for that specific gesture. All you have to do from here is add an observer for the notification you posted and then make able for the user to swipe. Let me know if this was useful.

Kind Regards

like image 1
Bruno Garelli Avatar answered Nov 17 '22 13:11

Bruno Garelli