繁体   English   中英

UITableView中的iOS6和屏幕外UITextView

[英]iOS6 and offscreen UITextView in UITableView

我有一个UITableViewController,每个单元格中都有一个UITextField。 当用户在字段中点击返回时,它会自动将下一个字段设置为第一个响应者,并滚动表格以显示该字段,如下所示:

- (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可见)它按预期工作,但它看起来很hacky并且不那么顺利,所以我宁愿理解什么是错误的,而不是实现像那。

在我对这个问题的解决方案中,我将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;
}

希望有所帮助。

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

不幸的是,Jeffrey Thomas的解决方案并不适合我。 如果单元格在屏幕外,则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中的一个错误,我计划将来不再使用UITableView作为表单。

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

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView

这也是表视图触发的( UITableViewDelegate符合UIScrollViewDelegate ),当它完成滚动以响应表视图方法时

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

所以关键是要计算你想要在下一个/上一个方法中选择的行的索引路径(比如Jeffrey Thomas的- (IBAction)advanceToNextTextField方法),但是不要选择它,只需滚动到它,然后设置一个ivar为了它:

[_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;
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM