代码之家  ›  专栏  ›  技术社区  ›  progrmr

当我的UITableViewCell外的某个东西被触摸时,我如何判断?

  •  4
  • progrmr  · 技术社区  · 14 年前

    类似 this question 我有一个UITableViewCell的自定义子类,它有一个UITextField。它的工作很好,除了键盘,当用户接触到不同的表视图单元格或表外的其他内容时,它不会消失。我正试图找出最佳的地方来找出什么时候手机外的东西被触摸,然后我可以在文本字段上调用resignfirstresponder。

    如果UITableViewCell可以在其视图之外接收触摸事件,那么它可以重新设置FirstResponder本身,但我看不到任何方法可以在单元中获取这些事件。

    编辑: 我在我的UITableViewCell子类中尝试了这个方法(如下),但它不起作用,我认为这是因为如果事件由控件处理,则不会调用TouchsBegan:WithEvent:我想我需要在事件被发送到响应链之前抓住它们。

    我正在考虑的解决方案是向视图控制器添加touchebegan:withEvent:method。在那里,我可以向所有可见的TableView单元格发送ResignFirstResponder,但触摸所在的单元格除外(让它获取触摸事件并自行处理)。

    可能是这样的伪代码:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        CGPoint touchPoint = // TBD - may need translate to cell's coordinates
    
        for (UITableViewCell* aCell in [theTableView visibleCells]) {
            if (![aCell pointInside:touchPoint withEvent:event]) {
                 [aCell resignFirstResponder];
            }
        }
    }
    

    我不确定这是不是最好的方法。对于TableViewCell本身,似乎没有任何方法可以接收其视图之外事件的事件通知。

    编辑2: 我以为我有一个答案(我甚至把它作为一个答案贴出来),使用hitest:withevent:但是没有成功。不总是有人打电话给它。:

    3 回复  |  直到 14 年前
        1
  •  10
  •   progrmr    14 年前

    [编辑:删除了以前的尝试,但并不总是有效,此尝试确实有效]

    好吧,我终于想出了一个完全可行的解决方案。我将UITableView子类化,并覆盖了HitTest:WithEvent:方法。它被调用用于表视图中任何地方的所有触摸,只有其他可能的触摸在导航栏或键盘中,并且表视图的HitTest不需要知道这些。

    这将跟踪表视图中的活动单元格,并且每当您点击不同的单元格(或非单元格)时,它会向处于非活动状态的单元格发送resignfirstresponder,从而使其有机会隐藏其键盘(或日期选择器)。

    -(UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event
    {
        // check to see if the hit is in this table view
        if ([self pointInside:point withEvent:event]) {
            UITableViewCell* newCell = nil;
    
            // hit is in this table view, find out 
            // which cell it is in (if any)
            for (UITableViewCell* aCell in self.visibleCells) {
                if ([aCell pointInside:[self convertPoint:point toView:aCell] withEvent:nil]) {
                    newCell = aCell;
                    break;
                }
            }
    
            // if it touched a different cell, tell the previous cell to resign
            // this gives it a chance to hide the keyboard or date picker or whatever
            if (newCell != activeCell) {
                [activeCell resignFirstResponder];
                self.activeCell = newCell;   // may be nil
            }
        }
    
        // return the super's hitTest result
        return [super hitTest:point withEvent:event];   
    }    
    

    在具有uitextfield的uiTableViewCell子类中,我添加了以下代码以摆脱键盘(或日期选择器,它像键盘一样向上滑动):

    -(BOOL)resignFirstResponder
    {   
        [cTextField resignFirstResponder];  
        return [super resignFirstResponder];
    }
    

    哎呀!

        2
  •  0
  •   Tom    14 年前

    我觉得你走对了,但是 touchesBegan:withEvent: 是一个uiresponder方法,因此实际上您必须在uiview子类中重写它,而不是在uiviewcontroller子类中。您的选择是:

    • 如果已经对UITableViewCell进行了子类化,请重写 触摸屏:带事件: 那里。
    • 如果使用的是标准的UITableViewCell,请实现 tableView:didSelectRowAtIndexPath 在UITableView的委托中。
        3
  •  0
  •   dhvidding    14 年前

    这是一个很好的解决方案,是我在网上找到的最好的解决方案。我发现的唯一问题是,如果你从一个文本字段的单元格切换到另一个,键盘就会消失并重新出现,导致一个不稳定的类型动画。