检测 UITableViewCell 子视图内的触摸
Posted
技术标签:
【中文标题】检测 UITableViewCell 子视图内的触摸【英文标题】:Detecting touch inside UITableViewCell subview 【发布时间】:2014-07-23 15:46:02 【问题描述】:我不清楚应该在哪里将 UIGestureRecognizer 代码添加到 UITableViewCell 的相应子视图中。我已经阅读了我能找到的所有相关问题。现在我的单元格和单元格的子视图在 cellForRowAtIndexPath 内生成。我试图在 cellForRowAtIndexPath 中添加手势:
UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[mySubview addGestureRecognizer:tapGesture];
tapGesture.cancelsTouchesInView = YES;
tapGesture.delegate = self;
但是,这并没有检测到任何东西。为了验证我的 UIGesture 识别器是否正常工作,我在 tableView 本身上使用了上面的代码,它确实按预期注册了触摸。此外,当 tableView 附加了上述手势时,也会按预期调用以下代码:
-(BOOL) gestureRecognizer:(UITapGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
NSLog(@"shouldRevceiveTouch");
return YES;
- (BOOL)gestureRecognizer:(UITapGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UITapGestureRecognizer *)otherGestureRecognizer
NSLog(@"simultaneously");
return YES;
我试图从 tableView 和 cellForRowAtIndexPath 内部删除 GestureRecognizer 我试图将 GestureRecognizer 附加到单元格本身,它的任何子视图,没有检测到任何其他内容。 (以上代码均未触发)
显然我错误地添加了 GestureRecognizer。在哪里/何时是添加 GestureRecognizer 的合适位置/时间?
谢谢。
【问题讨论】:
我认为如果 mySubview 不是 nil 并且它的 userInteractionEnabled 属性设置为 yes,您显示的代码应该可以工作。 mySubview 是什么类型的视图? 如果子视图是 UILabel 类型,请启用 userInteraction 属性为 true。 【参考方案1】:我做过类似的事情,但它是UILongPressGestureRecognizer
。我认为没有太大的区别(因为所有的触摸都是由UITableView
接收的)。我在控制器 viewDidLoad
方法中添加了手势识别器(不在单元格中)。
- (void) tableViewLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
CGPoint p = [gestureRecognizer locationInView:self.messageTableView];
NSIndexPath *indexPath = [self.messageTableView indexPathForRowAtPoint:p];
if (indexPath == nil)
NSLog(@"long press on table view but not on a row");
else
UITableViewCell *cell = [self.messageTableView cellForRowAtIndexPath:indexPath];
CGPoint pointInCell = [cell convertPoint:p fromView:self.messageTableView];
你可以把长按换成普通的,自己试试
【讨论】:
谢谢,我决定走这条路。在检测该点是否在视图框架中时,我现在遇到了一个单独的问题。如果我单击框架的上半部分,并且在框架上方一点,就会检测到该点。现在正在努力。 @tpdietz 我认为您可以尝试将点转换为单元坐标空间,但转换为所需的 UIView。【参考方案2】:我需要检测对单元格内不同子视图的触摸。还处理 ios 9 的 UITableViewCellContentView。
首先,我在自定义 UITableViewCell
中覆盖了 touchesBegan- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:touch.view];
// Imagine I have 2 labels inside my cell
CGPoint convertedPoint = [self.firstLabel convertPoint:point fromView:touch.view];
if ([self.firstLabel pointInside:convertedPoint withEvent:nil])
// Touched first label
return;
convertedPoint = [self.secondLabel convertPoint:point fromView:touch.view];
if ([self.secondLabel pointInside:convertedPoint withEvent:nil])
// Touched second label
return;
// no labels touched, call super which will call didSelectRowAtIndexPath
[super touchesBegan:touches withEvent:event];
为了修复 iOS 9 中的支持,我们应该覆盖 awakeFromNib 或者如果单元格不在 Storyboard / xib 中,则只禁用单元格用户交互:
- (void)awakeFromNib
// Initialization code
self.contentView.userInteractionEnabled = NO;
当然,我们不应该忘记启用标签用户交互。
【讨论】:
【参考方案3】:不确定您到底要做什么。如果您只想检测用户是否点击了表格中的单元格,那么您不需要实现手势识别器。只需实现下面的委托方法来检测何时选择了表中的行,然后处理该行的元素,例如获取子视图等。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
// Do all my cool tap related stuff here for example, get the row that was tapped:
UITableViewCell *cell= [tableView cellForRowAtIndexPath:indexPath];
// get your subview (assume its a UIImageView) from cell - one way to do it below
UIImageView photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
如果您进一步描述您的问题,那么也许我可以提供其他建议。
【讨论】:
以上是关于检测 UITableViewCell 子视图内的触摸的主要内容,如果未能解决你的问题,请参考以下文章
UITableViewCell 内的 UIScrollView - 水平滚动
iOS 增加 UITableViewCell 中 UIButton 的触控区域