【问题标题】:Touch events on UITableView?UITableView 上的触摸事件?
【发布时间】:2011-08-16 10:25:35
【问题描述】:

我在视图中有 UIViewControllerUITableView 作为孩子, 我想要做的是当我触摸任何在底部显示视图的行时。如果用户触摸行或底部视图之外的任何其他位置,我想隐藏该视图。

问题是当我点击UITableView 时它不会触发touchesEnded 事件。

现在我如何检测UITableView 上的触摸并与行选择事件区分开来。

谢谢。

【问题讨论】:

  • 我不确定我是否理解。你的意思是你有一个 UIView (viewA) 包含一个 UITableView 和另一个 UIView (viewB) (在底部)。如果用户触摸了 UiTableViewCell 或 viewB 以外的任何地方,那么您希望隐藏 viewB。否则,显示视图 B。对吗?
  • 是的,这正是我想做的。如果用户触摸 UITableViewCell,我想显示 viewB。我可以通过 didRowSelectedAtIndexPath:
  • 那么您是在问..“您如何捕获 UITableView 上发生的触摸事件,而不是单元格中发生的触摸事件?”
  • 是的,当然.. 我需要检测 UITableView 而不是单元格的触摸

标签: iphone uitableview uiviewcontroller touches


【解决方案1】:

无需子类化任何东西,您可以将UITapGestureRecognizer 添加到UITableView 并根据您的标准吸收或不吸收手势。

在你看来DidLoad:

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];
    ...
}

希望对某人有所帮助。

【讨论】:

  • 我更喜欢在 scrollViewWillBeginDragging:(UIScrollView *)scrollView 方法中调用 resignFirstResponder,而不是 scrollViewDidScroll。因为如果用户在滚动减速期间滚动然后单击 searchBar - 键盘将出现在屏幕上一秒钟然后它会隐藏这是不合适的行为。使用 scrollViewWillBeginDragging 方法可以解决这个问题。
【解决方案2】:

您应该将触摸事件转发给视图的控制器。 子类化您的 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 
}

然后,你可以在控制器的触摸方法中做你想做的事情。

【讨论】:

  • 谢谢@longway,但我没有得到 touchsBegan 的调用,我怎么能将它转发到视图的控制器???问题都是关于当我触摸 tableView 时如何调用 touchesBegan 事件:)
  • 你继承 UItableView,覆盖触摸句柄方法。然后你使用自定义的 tableview 类创建你的表
  • 嗨,我已经尝试过你的解决方案,它当然可以检测 tableview 上的 topuch 并传递给相应的 superview。现在我遇到了 UITableview 委托方法的问题,即 didSelectRowAtIndexPath 没有被调用。最终我想要的是,首先检测 tableview 上的触摸传递它 superview 做一些动作,然后执行 didSelectRowAtIndexPath。你能帮我吗??
【解决方案3】:

我只是偶然发现了可能解决您问题的方法。创建表格视图时使用此代码:

tableView.canCancelContentTouches = NO;

如果不将此设置为NO,则只要表格视图中有一点垂直移动,触摸事件就会被取消(如果您将 NSLog 语句放入代码中,您会看到touchesCancelled表格开始垂直滚动时立即调用)。

【讨论】:

  • 您的解决方案不起作用。我尝试了您的解决方案并使用了所有带有日志的触摸事件,包括touchesCancelled。在viewDidLoad 中,我设置了[tblTemp setCanCancelContentTouches:NO];。没有调用我的触摸方法。
【解决方案4】:

我长期以来一直面临这个问题并且没有任何有效的解决方案。最后我选择了另一种选择。从技术上讲,我知道这不是解决方案,但这可能有助于肯定寻找相同解决方案的人。

在我的情况下,我想选择一个行,然后我触摸表格或视图上的任何位置我想隐藏这些选项或执行任何任务,除了之前选择的行之外,我做了以下操作:

  1. 为视图设置触摸事件。当您触摸除表格视图之外的视图上的任何位置时,这将执行该任务。

  2. 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;
        }
     }
    

我知道这是较旧的帖子,不是一个好的技术解决方案,但这对我有用。我发布此答案是因为这肯定会对某人有所帮助。

注意:这里写的代码可能有拼写错误,因为这里是直接输入的。 :)

【讨论】:

    【解决方案5】:

    试试这个方法:

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
    
    }
    
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {
    
    }
    

    使用 scrollViewDidEndDragging 替代 touchesEnded。希望对您有所帮助。

    【讨论】:

      【解决方案6】:

      要在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];
      }
      

      【讨论】:

        【解决方案7】:

        在你的控制器类中声明一个移除底部视图的方法。像这样的:

        -(IBAction)bottomViewRemove:(id)sender {
        
        [bottomView removeFromSuperview];
        
        }
        

        在 Interface Builder 中,选择您的视图,然后在自定义类部分的身份检查器中,将类从 UIView 更改为 UIControl。之后转到连接检查器并将 TouchUpInside 事件连接到上面声明的方法。希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-17
          • 2011-05-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多