scrollToRowAtIndexPath 在 Top 时必须调用两次

Posted

技术标签:

【中文标题】scrollToRowAtIndexPath 在 Top 时必须调用两次【英文标题】:scrollToRowAtIndexPath must be called twice when at Top 【发布时间】:2013-02-26 21:30:14 【问题描述】:

我有一个 tableView,我允许用户使用一些箭头键导航文本字段。但是,当用户位于表格顶部时,必须按下箭头按钮两次,然后第一响应者才会真正改变。第一次单击显示下一个单元格,第二次单击实际上将焦点移动到上面单元格中的 textField。所有其他方向和箭头都可以在焦点更改和滚动发生的地方单击。用户位于底部时除外。同样的事情也会发生。 (但是用户不能这样做,因为当用户选择文本字段时我将滚动设置为顶部)

有没有办法即使在桌子的顶部也能获得相同的视觉效果?

我的代码...

switch (arrowButton.tag) 
    case UpArrow:
        destinationIndex =  [NSIndexPath  indexPathForRow:currentIndex.row - 1 inSection:currentIndex.section];
        newTag = currentTextField.tag;
        break;
    case LeftArrow:
            // Move back one textField.
        if (currentTextField.tag == CustomerDetailsOrderViewControllerCellLeftTextField) 
            // Selected text field is on left.  Select right textfield in the row above
            destinationIndex = [NSIndexPath  indexPathForRow:currentIndex.row - 1 inSection:currentIndex.section];
            newTag = CustomerDetailsOrderViewControllerCellRightTextField;
         else 
            // Selected text field is on right.  Select the left textfield in the same row
            destinationIndex = currentIndexPath;
            newTag = CustomerDetailsOrderViewControllerCellLeftTextField;
            
        break;
    case RightArrow:
        // Move forward one textField.
        if (currentTextField.tag == CustomerDetailsOrderViewControllerCellLeftTextField) 
            // Selected text field is on Left.  Select right textfield
            destinationIndex = currentIndexPath;
            newTag = CustomerDetailsOrderViewControllerCellRightTextField;
         else 
            // Selected text field is on right.  Select the left textfield in the row below
            destinationIndex = [NSIndexPath  indexPathForRow:currentIndex.row + 1 inSection:currentIndex.section];
            newTag = CustomerDetailsOrderViewControllerCellLeftTextField;
        
        break;
    case DownArrow:
        destinationIndex =  [NSIndexPath  indexPathForRow:currentIndex.row + 1 inSection:currentIndex.section];
        newTag = currentTextField.tag;
        break;
    default:
        break;

[_tableView scrollToRowAtIndexPath:destinationIndex atScrollPosition:UITableViewScrollPositionNone animated:YES];
newTextFieldSelection = (UITextField *)[[_tableView cellForRowAtIndexPath:destinationIndex] viewWithTag:newTag];
[newTextFieldSelection becomeFirstResponder];

【问题讨论】:

当您使用dispatch_after 稍微延迟后执行最后一行代码时会发生什么? 我对 dispatch_after 不熟悉,但我添加了一个计时器和一些断点。显然发生了什么,滚动动画在该函数中的所有内容执行后发生。 杰西,这就是为什么我说延迟后执行最后两行。 【参考方案1】:

杰西,是动画害死你。

试试

    [_tableView scrollToRowAtIndexPath:destinationIndex atScrollPosition:UITableViewScrollPositionNone animated:NO];
    newTextFieldSelection = (UITextField *)[[_tableView cellForRowAtIndexPath:destinationIndex] viewWithTag:newTag];
    [newTextFieldSelection becomeFirstResponder];

    [_tableView scrollToRowAtIndexPath:destinationIndex atScrollPosition:UITableViewScrollPositionNone animated:NO];
    newTextFieldSelection = (UITextField *)[[_tableView cellForRowAtIndexPath:destinationIndex] viewWithTag:newTag];
double delayInSeconds = 1.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        newTextFieldSelection = (UITextField *)[[_tableView cellForRowAtIndexPath:destinationIndex] viewWithTag:newTag];
        [newTextFieldSelection becomeFirstResponder];
    );

那些又快又脏。您可以更进一步,在表格的 contentOffset 上使用 KVO,并在动画完成后执行您的 firstResponder 业务。

【讨论】:

以上是关于scrollToRowAtIndexPath 在 Top 时必须调用两次的主要内容,如果未能解决你的问题,请参考以下文章

scrollToRowAtIndexPath 错误

UITableView scrollToRowAtIndexPath

scrollToRowAtIndexPath 在 Top 时必须调用两次

我对“scrollToRowAtIndexPath”有疑问。我得到这个错误。 (我已经上传了课程)

scrollToRowAtIndexPath 在 3/4 行之后没有滚动到正确的行

scrollToRowAtIndexPath 上非常奇怪的 UITableViewController.tableview 行为