单击UITableViewCell中的UITextField

时间:2008-12-08 20:57:32

标签: iphone objective-c cocoa-touch

我遇到一个问题,即在textField中点击UITableViewCell时,方法tableView:didSelectRowAtIndexPath:不会被调用。问题是,我需要将我的tableView滚动到正确的位置,否则键盘就会越过第一个响应者。

我必须像这样移动代码:

[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

加入我的tableView委托方法和我的UITextField委托方法textFieldDidBeginEditing:

是创建新方法的最佳方法,将单击的单元格/文本字段的indexPath传递给它,并从tableView委托和UITextField委托调用该方法?更好的办法吗?

11 个答案:

答案 0 :(得分:22)

我发现以下效果很好(它假设您在表视图控制器中)

- (void)textFieldDidBeginEditing:(UITextField *)textField{  
    CGPoint pnt = [self.tableView convertPoint:textField.bounds.origin fromView:textField];
    NSIndexPath* path = [self.tableView indexPathForRowAtPoint:pnt];
    [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

答案 1 :(得分:9)

有几种方法可以解决此问题。会发生的事情是tableViewCell将触摸事件委托给其子视图,这会导致文本字段处理触摸而不是您的单元格。

解决此问题:

  • 将UITextfield的userinteractionEnabled属性设置为NO,然后当您获得didSelectRowAtIndexPath消息时,重新启用userInteractionEnabled并调用TextField的becomeFirstResponder。在v2.2上你甚至不需要设置userInteractionEnabled标志,我没有用其他版本测试过这个,但是文档很清楚你应该启用它。在tableViewController中,您只需要保存索引路径,直到获得UIKeyboardDidShow消息

  • 为UITextField创建一个委托,该委托报告回tableViewController,以便您可以从那里设置滚动偏移。

  • 注册键盘事件,然后通过检查编辑模式中的文本字段来确定scrolloffset

答案 2 :(得分:6)

您可以将控制器设置为UITextField的代理,然后在textFieldDidBeginEditing:textFieldShouldBeginEditing:

中调整表格视图

答案 3 :(得分:3)

我没有在网上找到任何适合我的解决方案。经过几天的谷歌搜索和实验,我终于把这个发布好了。这是Apple iPhone中的复杂错误,您将在本文末尾看到。

如果你遇到像我这样的问题如下:

  1. 让tableviewcell大于iphone屏幕的一半(不要与Apple的UICatalog的例子混淆,有一个不到50分的短tableview单元,这里不适用。),

  2. 在单元格中有多个uitexfields或uitextfield和uitextview或uiwebview的组合,

  3. 在uitextfields和uitextview或uiwebview之间点击会导致无法预测的滚动位置,点击的uitextfield会跳出视图或被keybaord覆盖。它仅在键盘出现在tableviewcell中时才第一次工作,并且随后无法正常工作。

  4. 在阅读与此类似的帖子后,我有了重大突破:http://alanduncan.net/old/index.php?q=node/13他们也没有完全正确。痛苦是由UIKeyboard事件中的错误引起的。当键盘首次出现时,它会发出UIKeyboardWillShowNotification和UIKeybaordDidShowNotification。 Theree是iPhone中的一个错误,不知何故,第一个UIKeyboardWillShowNotification与随后的UIKeyboardWillShowNotification不同。解决方案是OBSERVE UIKeyboardDidShowNotification。因此,当您的单元格出现时,请添加以下代码

     NSNotificationCenter*nc=[NSNotificationCenter defaultCenter];
        [nc addObserver:self selectorselector(keyboardDidShow name:UIKeyboardDidShowNotification object:self.window];
    

    在keyboardDidShow函数中,我们需要滚动TABLEVIEW,而不是像上面帖子中建议的tableviewcell。或者您可能会看到各种对象分开,而不是一起滚动。

    (void)keyboardDidShow:(NSNotification *)notif
    {
        //1. see which field is calling the keyboard
        CGRect frame;
        if([textField_no1 isFirstResponder])
        frame=textField_no1.frame;
        else if([textField_no2 isFirstResponder])
        frame=textField_no2.frame;
        else if([textField_no3 isFirstResponder])
        frame=textField_no3.frame;
        else if([textView isFirstResponder])
        frame=textView.frame;
        else return;
        CGRect rect=self.superview.frame;
    
        //2. figure out how many pixles to scroll up or down to the posistion set by theKeyBoardShowUpHorizon.
    
        //remove the complexity when the tableview has an offset
        [((UITableView*)[self.superview).setContentOffset:CGPointMake(0,0) animated:YES];
    
        int pixelsToMove=rect.origin.y+ frame.origin.y-theKeyBoardShowUpHorizon;
    
        //3. move the uitableview, not uitableviewcell
        [self moveViewUpOrDownByPixels:pixelsToMove];
    
    }
    
    - (void)moveViewUpOrDownByPixels:(int)pixels
    {
    
       [UIView beginAnimations:nil context:NULL];
       [UIView setAnimationDuration:0.6];
    
       //find the position of the UITableView, the superView of this tableview cell.
       CGRect rect=self.superview.frame;
    
       //moves tableview up (when pixels >0) or down (when pixels <0)
       rect.origin.y -= pixels;
       rect.size.height += pixels;
       self.superview.frame = rect;
       [UIView commitAnimations];
    }
    

    要恢复tableView,你需要在UIKeyboardDidHideNotification上添加观察者(不是其他帖子建议的UIKeyboardWillHideNotification,以避免闪烁),每次你都会出现tableviewcell,并将tableview放回原处。

    [nc addObserver:self selectorselector(keyboarDidHide) name:UIKeyboardDidHideNotification object:nil];
    
    - (void)keyboardDidHideNSNotification*)notif
    {
        //we have moved the tableview by number of pixels reflected in (self.superview.frame.origin.y). We need to move it back
        [self moveViewUpOrDownByPixels:self.superview.frame.origin.y];
    }
    

    不要忘记在[[NSNotificationCenter defaultCenter] removeObserver删除单元格消失时删除两个观察者:...

    这就是全部。我希望苹果iPhone团队有一天会解决这个问题,可能会在几个月内解决这个问题。

答案 4 :(得分:3)

我找到了解决方案。

  1. 在界面构建器中打开.xib文件。
  2. 选择表格视图
  3. 从IB菜单中选择工具 - &gt;尺寸检查器 在滚动视图大小部分,修改插入 - &gt;底值为100,150,250,具体取决于您的表格视图的大小。
  4. <强>代码

    -(void) textFieldDidBeginEditing:(UITextField *)textField 
    {
        UITableViewCell *cell = (UITableViewCell *) [[textField superview] superview];
        [self.tableView scrollToRowAtIndexPath:[tableView indexPathForCell:cell]
        atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
    

答案 5 :(得分:3)

我发现实际上很容易做到这一点。

UITextField委托方法textFieldDidBeginEditing将为您提供文本字段,然后您可以使用以下方法将其映射到indexPath:

self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin];

然后您可以将单元格滚动到视图中(即在您的UIKeyboardDidShowNotification键盘通知处理程序中):

[self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];

答案 6 :(得分:1)

不会为UITextField嵌入单元格调用didSelectRowAtIndexPath;因此,滚动逻辑需要在其他地方。

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
    UITableViewCell *cell = [_tableView cellForRowAtIndexPath:indexPath];
    [_tableView setContentOffset:CGPointMake(0, cell.frame.size.height) animated:YES];
}

确保将textField委托连接到自己

答案 7 :(得分:0)

注册UIKeyboardWillShowNotification和UIKeyboardWillHideNotification,然后根据需要在通知处理程序中调整视图。其中一个示例应用程序显示了如何执行此操作,但我忘记了哪些... SQLiteBooks,或者EditableDetailView。

答案 8 :(得分:0)

我正在努力解决同样的问题,我在UITableViewCells中有UITextFields,并且在编辑时无法获得视图滚动到该字段。我的解决方案的核心如下。

此代码的关键是创建UITextField的行。它不是在CGRectMake()函数中对x和y值进行硬编码,而是使用放置它的单元格中的x和y(+/-你希望从单元格边缘得到的任何偏移量,如下所示)。 UITextField *中的硬编码x和y值为每个单元格提供每个UITextField *的相同的 x,y帧位置(当显示时,它显然被单元格框覆盖),因此当您调用' scrollRectToVisible'代码它似乎没有正确的坐标,它应滚动。

1)创建单元格,并使用单元格的框架x和y值将UITextField *添加到单元格(我在这里包括可选的偏移

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell* cell;
    cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"UITableViewCell"] autorelease]; 

    //this is the critical part: make sure your UITextField* frame is based on the frame of the cell in which it's being placed.
    UITextField* txtField = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+20, cell.frame.origin.y+9, 280, 31)];
    txtField.delegate = self;

    [cell addSubview:txtField];
    return cell;
}

2)调整textFieldDidBeginEditing

中的滚动视图
-(void) textFieldDidBeginEditing:(UITextField *)textField {

    CGRect textFieldRect = [textField frame];
    [self.tableView scrollRectToVisible:textFieldRect animated:YES];
}

答案 9 :(得分:0)

由于没有简单的方法可以确定用户是否点击了文字字段或是通过becomeFirstResponder激活了这个问题,这个问题更加严重。

我能想出的最优雅的解决方案是在单元子类上实现hitTest:withEvent:,并且在选择单元格之前基本上假装文本字段不存在。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *view = [super hitTest:point withEvent:event];

    if(view == self.textField && !self.selected) {
        return self;
    }

    return view;
}

tableView:didSelectRowAtIndexPath:然后应手动将文本字段作为第一响应者。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    TextFieldCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];

    [cell.textField becomeFirstResponder]

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

最后,我们必须在完成编辑后取消选择该行。这可以通过UITextField委托或通过键盘通知完成,无论您喜欢什么。

- (void)textFieldDidEndEditing:(UITextField *)textField {
   [self.view endEditing:YES];
}

答案 10 :(得分:0)

我们有一个名为TPKeyboardAvoiding的控制器,它处理了有关tableview和scrollview的动态自动滚动的所有内容。 您可以从下面的代码下载示例代码。 https://github.com/NarayanaRao35/TPKeyboardAvoiding