2012-10-04 22 views
3

我有一个UITableViewController在每个单元格中都有一个UITextField。当用户点击一个字段返回,它会自动将下一个字段是第一个响应并滚动表显示领域,像这样:iOS6和屏幕外的UITextView在UITableView

- (BOOL) textFieldShouldReturn:(UITextField *)textField 
{ 
    UITextField *nextTextField=nil; 
    NSInteger row; 
    NSInteger section; 

    if(textField == self.txtFieldA) 
    { 
     nextTextField = self.txtFieldB; 
     row=1; section=0; 
    } 
    else if(textField == self.txtFieldB) 
    { 
     nextTextField = self.txtFieldC; 
     row=2; section=0; 
    } 
    else 
    { 
     [textField resignFirstResponder]; 
    } 

    if(nextTextField) 
    {   
     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section]; 
     [nextTextField becomeFirstResponder]; 

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

当您选择文本字段中的问题来(说txtFieldA ),向下滚动表格以便txtFieldB不可见,然后按Enter键。它在iOS5上按预期工作(txtFieldB成为新的第一响应者)。但是,在iOS6上它没有。它滚动到表格中的正确位置,但txtFieldB不成为第一响应者(我不确定是什么 - 当我在导航控制器上点击“返回”时,键盘保持可见状态)。

当我点击“返回”时,txtFieldB的didBeginEditing未被触发。如果我将[nextTextField becomeFirstResponder]延迟了一秒钟左右(直到滚动动画完成,这使得nextTextField可见),它的工作方式与预期的一样,但它看起来很乱,不那么流畅,所以我宁愿明白发生什么事情比实现类似的东西。

回答

2

在我对这个问题的解决方案中,我将UITableViewCell分类为一个文本字段单元格。在该文本字段单元格中,我覆盖了-setSelected:animated:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated 
{ 
    [super setSelected:selected animated:animated]; 

    if (selected) { 
     [self.textField becomeFirstResponder]; 
    } 
} 

早在我的视图控制器,当我要前进到下一个领域,我只是在选择它的行。

- (IBAction)advanceToNextTextField 
{ 
    NSIndexPath *indexPath = [self nextIndexPathFromIndexPath:self.indexPathOfActiveField]; 

    [self.tableView selectRowAtIndexPath:indexPath 
           animated:YES scrollPosition:UITableViewScrollPositionNone]; 
    [self.tableView scrollToRowAtIndexPath:indexPath 
          atScrollPosition:UITableViewScrollPositionNone animated:YES]; 
} 

这使得处理返回键容易。

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    switch (textField.returnKeyType) { 
     case UIReturnKeyNext: [self advanceToNextTextField]; break; 
     case UIReturnKeyDone: [self resignFirstResponder]; break; 
     default:    break; 
    } 

    return YES; 
} 

希望有所帮助。

+0

这绝对是一种更好的方式来设置它,但我不确定这将解决在下一个单元离开屏幕时点击“下一步”的问题。当您在iOS6上编译代码时,此代码是否工作? – Ned

+0

是的,它适用于iOS6。此代码直接从我的应用程序中拉出,该应用程序旨在运行iOS5和iOS6。 –

0

我还有一个现有的项目,在iOS 6之前工作正常。我的通用应用程序使用UITableView在键盘工具栏(类似于Safari)上创建带有“下一个”和“上一个”按钮的窗体。该表显示包含文本字段的UITableViewCell子类的实例。下一个/上一个功能也会打包 - 因此最后一个字段的“下一个”会将焦点返回到表单的顶部。

不幸的是,杰弗里托马斯的解决方案并不适合我。如果单元格不在屏幕上,则advanceToNextField方法中的select-and-scroll方法对单元格本身工作良好。在setSelected方法中,文本字段的视图层次结构是正确的:UITextField - >UITableViewCellContentView - >UITableViewCell子类 - >UITableView

然而,becomeFirstResponder调用仍然未能激活该字段的编辑模式,消防textFieldDidBeginEditing等的键盘仍然是可见的,但不会影响现在可见的细胞。

现在,我已经能够绕过这个问题是滚动第一没有动画的唯一途径:

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; 
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; 

像运Ned的延时技术,这保证了文本字段在应用程序要求它做出响应时可见。否则,看起来becomeFirstResponder在动画&期间正在触发文本字段(完全)可见之前。显然iOS 6中的一些更改对第一响应消息和可见性更严格!

不幸的是,当从一个领域移动到另一个领域时,这会失去很好的流体动画。假设这不仅仅是iOS 6.0中的一个bug,我打算在将来使用UITableView作为一种形式。

0

在我的同事Charles的帮助下找到了解决这个问题的方法(谢谢!)。我也尝试过杰弗里托马斯的解决方案(以及它的变体),但没有运气:如果其表格单元格在屏幕外,文本字段不会成为第一响应者,如Ogel所述。我寻找UITableViewDelegate方法,当桌面视图完成动画时会提醒我,并延迟调用文本字段的setSelected:方法,直到那时,没有运气。然后他向我指出

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 

也由表视图(UITableViewDelegate符合UIScrollViewDelegate),当它完成滚动响应表视图方法

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated 

所以关键在于解雇计算你打算在你的下一个/上一个方法来选择该行的索引路径(如杰弗里·托马斯的- (IBAction)advanceToNextTextField法),但不是选择它,只需滚动到它,并为它伊娃:

[_table scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 
_selectIndexPathOnAnimationEnd = nextIndexPath; 

然后在滚动视图的委托方法,在该指数的路径选择该行表视图已经完成滚动之后:

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 
    if(_selectIndexPathOnAnimationEnd != nil) { 
     [_table selectRowAtIndexPath:_selectIndexPathOnAnimationEnd animated:NO scrollPosition:UITableViewScrollPositionMiddle]; 
     _selectIndexPathOnAnimationEnd = nil; 
    } 
} 

此时文本字段可以成为第一个响应者。