我在视图中以UIViewController
和UITableView
为子项,
我想要做的是当我触摸任何一行时,我在底部显示一个视图。我希望隐藏该视图,如果用户触摸除了行或底部的任何地方。
问题是当我点击UITableView
时,它不会触发touchesEnded
事件。
现在我如何检测UITableView
上的触摸并将其与行选择事件区分开来。
感谢。
答案 0 :(得分:51)
无需任何子类,您可以向UITapGestureRecognizer
添加UITableView
并根据您的条件吸收手势。
在viewDidLoad中:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnTableView:)];
[self.myTableView addGestureRecognizer:tap];
然后,按照以下标准执行此操作:
-(void) didTapOnTableView:(UIGestureRecognizer*) recognizer {
CGPoint tapLocation = [recognizer locationInView:self.myTableView];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:tapLocation];
if (indexPath) { //we are in a tableview cell, let the gesture be handled by the view
recognizer.cancelsTouchesInView = NO;
} else { // anywhere else, do what is needed for your case
[self.navigationController popViewControllerAnimated:YES];
}
}
请注意,如果您只想在桌面上的任何位置单击,而不是单元格行中的任何按钮,则只需使用上面的第一个代码片段。一个典型的例子是当你有一个UITableView并且还有一个UISearchBar。您希望在用户单击,滚动等表视图时消除搜索栏。代码示例......
-(void)viewDidLoad {
[super viewDidLoad];
etc ...
[self _prepareTable];
}
-(void)_prepareTable {
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.allowsSelection = NO;
etc...
UITapGestureRecognizer *anyTouch =
[[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tableTap)];
[self.tableView addGestureRecognizer:anyTouch];
}
// Always drop the keyboard when the user taps on the table:
// This will correctly NOT affect any buttons in cell rows:
-(void)tableTap {
[self.searchBar resignFirstResponder];
}
// You probably also want to drop the keyboard when the user is
// scrolling around looking at the table. If so:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.searchBar resignFirstResponder];
}
// Finally you may or may not want to drop the keyboard when
// a button in one cell row is clicked. If so:
-(void)clickedSomeCellButton... {
[self.searchBar resignFirstResponder];
...
}
希望它有所帮助。
答案 1 :(得分:14)
您应该将触摸事件转发到视图的控制器。 对tableview控件进行子类化,然后重写方法:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event]; //let the tableview handle cell selection
[self.nextResponder touchesBegan:touches withEvent:event]; // give the controller a chance for handling touch events
}
然后,您可以在控制器的触摸方法中执行您想要的操作。
答案 2 :(得分:8)
我偶然发现了可能解决问题的方法。创建表视图时使用此代码:
tableView.canCancelContentTouches = NO;
如果没有将此设置为NO
,只要表格视图中有一点点垂直移动,触摸事件就会被取消(如果你在代码中放置了NSLog语句,你会看到{一旦表格开始垂直滚动,就会调用{1}}。
答案 3 :(得分:6)
我很长时间以来一直面临这个问题而且没有任何有效的解决方案。最后,我选择另类。我从技术上知道这不是解决方案,但这可能有助于有人找到同样的东西。
在我的情况下,我想选择一个显示某个选项的行,然后我触摸桌面上的任何位置或查看我想要隐藏这些选项或执行任何任务,除了之前选择的行,我执行了以下操作:
设置视图的触摸事件。当您触摸视图中除表视图之外的任何位置时,这将执行任务。
TableView的didSelectRowAtIndexPath执行以下操作
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
if(indexPath.row != previousSelectedRow && previousSelectedRow != -1) {
// hide options or whatever you want to do
previousSelectedRow = -1;
}
else {
// show your options or other things
previousSelectedRow = indexPath.row;
}
}
我知道这是较老的帖子而不是一个好的技术解决方案,但这对我有用。我发布这个答案是因为这可能对某些人有所帮助。
注意:这里写的代码可能有拼写错误,因为这里直接输入。 :)
答案 4 :(得分:3)
尝试这种方法:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
}
使用scrollViewDidEndDragging和touchesEnded的替代方法。希望它有所帮助。
答案 5 :(得分:2)
要在UITableView
使用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//<my stuff>
[super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//<my stuff>
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
//<my stuff>
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
//<my stuff>
[super touchesCancelled:touches withEvent:event];
}
答案 6 :(得分:-2)
在您的控制器类中声明一个删除底部视图的方法。像这样:
-(IBAction)bottomViewRemove:(id)sender {
[bottomView removeFromSuperview];
}
在Interface Builder中,选择您的视图,然后在自定义类部分的身份检查器中,将班级从UIView
更改为UIControl
。之后转到连接检查器并将TouchUpInside事件连接到上面声明的方法。希望这会有所帮助。