Iphone 单击UITableViewCell中的UITextField

Iphone 单击UITableViewCell中的UITextField,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我有一个问题,当在UITableViewCell中单击textField时,不会调用tableView:didSelectRowAtIndexPath:方法。问题是,我需要将我的tableView滚动到正确的位置,否则键盘会直接越过第一响应程序 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { TextFieldCell* cell = [self.t

我有一个问题,当在
UITableViewCell
中单击
textField
时,不会调用
tableView:didSelectRowAtIndexPath:
方法。问题是,我需要将我的
tableView
滚动到正确的位置,否则键盘会直接越过第一响应程序

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

    [cell.textField becomeFirstResponder]

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
然后我必须像这样移动代码:

[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
在my
tableView
delegate方法和my
UITextField
delegate方法中,
textFieldDidBeginEditing:


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

您可以将控制器设置为UITextField的代理,然后在
textFieldDidBeginEditing:
textFieldShouldBeginEditing:
注册UIKeyboardWillShowNotification和UIKeyboardWillHideNotification中调整表视图,然后根据需要在通知处理程序中调整视图。其中一个示例应用程序演示了如何执行此操作,但我忘记了是哪个…SQLiteBooks,或者EditableDetailView。

有几种方法可以解决此问题。发生的情况是,tableViewCell将触摸事件委托给其子视图,从而使textfield代替您的单元格处理触摸

要解决此问题,请执行以下操作:

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

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

  • 注册键盘事件,然后通过检查处于编辑模式的文本字段来计算滚动偏移量


我也遇到了同样的问题,在UITableViewCells中有UITextFields,在编辑时无法让view滚动到该字段。我的解决方案的核心如下

此代码的键是创建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];
}

我在网上找不到任何适合我的解决方案。经过几天的谷歌搜索和实验,我终于把这本书钉牢了。这是苹果iPhone中的一个复杂错误,你将在本文末尾看到

如果您遇到像我这样的问题,如下所示:

  • tableviewcell超过iphone屏幕的一半(不要与苹果UICatalog的示例混淆,因为tableviewcell短于50点,此处不适用)

  • 在单元格中有多个UITEXField,或在单元格中有UITEXField和uitextview或uiwebview的组合

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

  • 在阅读了与此类似的帖子后,我有了重大突破:他们也没有完全正确地理解。疼痛是由UIKeyboard事件中的错误引起的。当键盘第一次出现时,它会发出UIKeyboardWillShowNotification和UIKeybaordDidShowNotification。iPhone中存在一个漏洞,第一个UIKeyboardWillShowNotification与随后的UIKeyboardWillShowNotification有所不同。解决方案是观察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];
    }
    
    当您的单元格通过[[NSNotificationCenter defaultCenter]removeObserver:…]消失时,请不要忘记删除这两个observesr


    这就是全部。我希望苹果的iPhone团队有一天能解决这个问题,也许在几个月后的4.0版中。

    我找到了一个解决方案

  • 在interface builder中打开.xib文件
  • 选择表格视图
  • 从IB菜单中选择工具->尺寸检查器 在“滚动视图大小”部分,根据表格视图的大小,将“插入->底部值”修改为100、150、250
  • 代码

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

    我发现这其实很容易做到

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

    self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin];
    
    然后可以将单元格滚动到视图中(即在UIKeyboardDidShowNotification键盘通知处理程序中):


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


    UITextField嵌入不会调用didSelectRowAtIndexPath
    [self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
    
    - (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];
    }
    
    - (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];
    }
    
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        UIView *view = [super hitTest:point withEvent:event];
    
        if(view == self.textField && !self.selected) {
            return self;
        }
    
        return view;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        TextFieldCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
    
        [cell.textField becomeFirstResponder]
    
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
    }
    
    - (void)textFieldDidEndEditing:(UITextField *)textField {
       [self.view endEditing:YES];
    }