可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a tableviewCell
, where the user can scroll
horizontally. Since the scrollView
covers nearly the whole cell
, the tableView
method didSelectRow
gets not called if the user clicks the cell
.
So I thought, I could pass the touch event of the UIScrollView
to the cell
, but still the didSelectRow
doesnt gets called. I subclassed UIScrollView
to pass the touch event only, if the touch was not a drag:
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event { NSLog(@"touch scroll"); // If not dragging, send event to next responder if (!self.dragging) [self.superview touchesEnded: touches withEvent:event]; else [super touchesEnded: touches withEvent: event]; }
Any ideas on how to pass the click to the table, to get the delegate-methods called and keep the scrolling inside the scrollview
?
回答1:
You can actually do this without subclassing UIScrollView
. Whether you have a custom cell, or are setting properties in cellForRowAtIndexPath
in the UITableView
, you can do the following:
[cell.contentView addSubview:yourScrollView]; yourScrollView.userInteractionEnabled = NO; [cell.contentView addGestureRecognizer:yourScrollView.panGestureRecognizer];
The reason you can do this is because scrollView has its own panGestureRecognizer that's accessible to the programmer. So, just adding it to the cell's view will trigger the scrollview's gesture delegates.
The only drawback of this approach is that subviews of the scroll view are unable to receive any touch input. If you need this you will have to chose a different approach.
回答2:
I just encountered the same problem.
In your subclass make sure to include the full set of methods:
-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { if (!self.dragging) [self.superview touchesCancelled: touches withEvent:event]; else [super touchesCancelled: touches withEvent: event]; } -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (!self.dragging) [self.superview touchesMoved: touches withEvent:event]; else [super touchesMoved: touches withEvent: event]; } -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (!self.dragging) [self.superview touchesBegan: touches withEvent:event]; else [super touchesBegan: touches withEvent: event]; } -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (!self.dragging) [self.superview touchesEnded: touches withEvent:event]; else [super touchesEnded: touches withEvent: event]; }
回答3:
try set this
_scrollView.canCancelContentTouches = NO
also, it is bad to partially forward touch events
回答4:
The selected answer is correct, but I updated the code based on a bug I was getting.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (self.dragging) { [super touchesMoved:touches withEvent:event]; } else { if ([self.delegate isKindOfClass:[UITableViewCell class]]) { [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event]; } [self.superview touchesMoved:touches withEvent:event]; } }
If your self.delegate
is not the UITableViewCell
, than replace that property with a property to your cell.
The cell needs to retrieve the cancel touch event during movement to prevent the undesired results. It can be easily reproducible as follows.
- Highlight the cell (assuming the scroll view is over the whole cell, if not highlight the scroll view)
- While the cell is highlighted, drag the table view
- Select any other cell and now the previously highlighted cell will retrieve the
didSelectCell
state
Another point to mention is that order matters! If the self.delegate
is not called before the self.superview
then the highlighted state wont happen.
回答5:
Swift 3
scrollView.isUserInteractionEnabled = false contentView.addGestureRecognizer(scrollView.panGestureRecognizer)