1

I have a UITableView, for whom some (not all) UITableViewCells contain their own UITableView.

The default behavior I'm finding is, when trying to single-tap scroll (UIScrollViewPanGestureRecognizer) the outermost table, scrolling works just fine, but only when the tap begins on a cell not containing a nested UITableView. When the cell does contain a nested UITableView, that inner table's PanGestureRecognizer is invoked. This behavior is understandable and expected.

My desire is to disable all scrolling on the inner tables, and have any pan gestures that begin on them instead trigger/invoke scrolling on the outer table.

I have researched and tried several solutions, but without success.

Disabling all interaction in the nested cell isn't an option, because I need the ability to tap-select or swipe-delete cells within the nested table.

I was able to find and remove the inner table's UIScrollViewPanGestureRecognizer. This successfully disabled scrolling for the inner table. However, I couldn't get the outer table's UIScrollViewPangestureRecognizer to be invoked. Instead my outer table basically had "dead spots" (the cells having a nested table) where scrolling on the outer table wouldn't take place.

Everything I've read about the view hierarchy and hit-testing suggests that the above solution should simply work: the UITouch is wrapped in a UIEvent, and all possible receivers in the view hierarchy are thus queried. Strangely enough, from the debugger, my view hierarchy appears to be severed at the point of the inner UITableView. That is, for the UITableViewCell in question, its superview chain only leads to nil, not to the outermost table. Yet, using the Reveal App (www.revealapp.com), I have confirmed that my view hierarchy is indeed connected (which makes sense, otherwise the inner table wouldn't be rendering).

Lastly, I tried this code:

[innerTable.panGestureRecognizer requireGestureRecognizerToFail:outerTable.panGestureRecognizer];

Based on my references, this should do exactly what I'm seeking here -- the inner table won't capture the pan-gesture unless the outer table defers. But this code has no effect.

Any help you can provide is most appreciated -- this has been a confounding UI mystery for many days now!

Aaron Fi
  • 10,116
  • 13
  • 66
  • 91

3 Answers3

1

Just set scrolling to disabled in the inner table and set the content size of the table to be equal to the total size. Then add that table to your outer table and let it do all the scrolling. UITableView is a subclass of UIScrollView so look into the scrollview methods to help you configure the tableview to work within another.

Pete42
  • 916
  • 7
  • 15
1

My desire is to disable all scrolling on the inner tables

This is either massively patronising or you'll kick yourself, but you didn't mention it in the question, so have you tried this:

innerTableView.scrollEnabled = NO;

If that doesn't work, you probably need to set the view controller as the delegate of the pan recogniser gesture from both (all) table views and return YES for shouldRecognizeSimultaneouslyWithGestureRecognizer:

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • this works but you also need to set the content size or else you will never be able to see the rest of it or you will have to manually set the content offset on scrolling for the inner table – Pete42 Jan 03 '15 at 08:30
  • I'm assuming that's been done already and the cell is big enough to show the full inner table – jrturton Jan 03 '15 at 08:37
  • Not patronizing at all (I'm new at iOS, six weeks in). I didn't know about scrollEnabled. But trying it just now, had no effect. (At first I thought it did, but I was mistaken) – Aaron Fi Jan 03 '15 at 09:29
  • Ok, another option. Do make sure you've undone all of your other attempts up to now, to prevent odd side effects. – jrturton Jan 03 '15 at 09:33
  • Apologies -- I found in my old attempts that I had tried scrollEnabled. Tried it again just now -- it does the trick; but all rendering for each UITableViewCell in the inner table breaks; (each cell is just empty white space). It's quite possible this is an orthogonal problem, and that I gave up too early on this from before. Will keep at it. – Aaron Fi Jan 03 '15 at 09:38
  • Yeah, that doesn't sound related. – jrturton Jan 03 '15 at 09:39
  • Definitely on the right path. scrollEnabled = NO is what I want. But cell selection is still happening, so there's no ability for the inner table to respond to a tap-drag; instead it immediately traps the "tap" as a cell selection. Maybe I need to to [innerTable'sTapGestureRecognizer requireGestureRecognizerToFail:outerTable.panGestureRecognizer]; in addition to turning off scrollEnabled. – Aaron Fi Jan 03 '15 at 09:57
  • Seems very similar to my problem: http://stackoverflow.com/questions/4629499/how-to-steal-touches-from-uiscrollview – Aaron Fi Jan 03 '15 at 10:18
  • Does this require the table view's contentSize be fully expanded (i.e. fit all cells)? If so, will that create memory issues? http://oleb.net/blog/2014/05/scrollviews-inside-scrollviews/ – shaunlim Dec 30 '15 at 17:54
  • 1
    @shaunlim yes, but in most cases I'd expect the inner table to be pretty small, otherwise this is not a good design, from a code or UX perspective. – jrturton Dec 30 '15 at 18:06
0

You can set minimumNumberOfTouches to 2 for inner table's panGestureRecognizer. By this inner table will scroll on two fingers drag only(If this UX is acceptable.).

Rahul Wakade
  • 4,765
  • 2
  • 23
  • 25