在视图显示之前立即滚动到表格中的行

时间:2010-05-28 20:05:13

标签: iphone objective-c cocoa-touch uitableview scroll

带有表格的视图会被推到屏幕上,我希望它在屏幕实际显示之前滚动到表格中的某一行。我在最终的viewcontroller中使用了这段代码。

NSIndexPath *scrollToPath = [NSIndexPath indexPathForRow:5 inSection:0]; 
[theTable scrollToRowAtIndexPath:scrollToPath atScrollPosition:UITableViewScrollPositionTop animated:NO];

当我把它放在viewDiDAppear方法中时,它会从表格的初始位置(在顶部)短暂地闪烁到我想要的行。我不希望它显示初始位置。如果我将它放在viewDidLoad或viewWillAppear中,那么它会因NSRangeException崩溃,可能是因为该表尚未设置。

如何在不显示初始位置的情况下滚动它?

8 个答案:

答案 0 :(得分:15)

感谢Shaggy和Dying Cactus为我指明正确的方向。答案是加载表并在viewWillAppear中滚动:

-(void)viewWillAppear:(BOOL)animated
{
    [theTable reloadData];
    NSIndexPath *scrollToPath = [NSIndexPath indexPathForRow:5 inSection:0]; 
    [theTable scrollToRowAtIndexPath:scrollToPath atScrollPosition:UITableViewScrollPositionTop animated:NO];   
}

答案 1 :(得分:4)

我有完全相同的问题,在尝试了所有内容后,这很有用,关键是如果您使用自动布局,则必须在viewDidLayoutSubviews中编写scrollToBottom代码

将scrollToBottom初始化为true,然后执行此操作

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    // Scroll table view to the last row
    [self scrollToBottom];
}

-(void)scrollToBottom {
    if (shouldScrollToLastRow)
    {
        CGPoint bottomOffset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height);
        [self.tableView setContentOffset:bottomOffset animated:NO];
    } }

这样做可以确保您几乎位于桌面底部,但可能不会处于最底层,因为当您处于最顶端时,无法知道确切的底部偏移量tableView,之后我们可以实现scrollViewDidScroll

-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    // if you're not at bottom then scroll to bottom
    if (!(scrollOffset + scrollViewHeight == scrollContentSizeHeight))
    {
        [self scrollToBottom];
    } else {
    // bottom reached now stop scrolling
        shouldScrollToLastRow = false;
    }
}

答案 2 :(得分:3)

scrollToRowAtIndexPath:中调用viewWillAppear:对我不起作用,因为尚未加载tableView。但是我可以在延迟一段时间后调用scrollToRowAtIndexPath:来解决这个问题。

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

    [self performSelector:@selector(scrollToCell) withObject:nil afterDelay:0.1];
}

- (void) scrollToCell
{
    [_tableView reloadData];
    NSIndexPath *scrollToPath = [NSIndexPath indexPathForRow:5 inSection:0];
    [_tableView scrollToRowAtIndexPath:scrollToPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

希望它会对某人有所帮助。

答案 3 :(得分:2)

  

如果我把它放在viewDidLoad或   viewWillAppear然后崩溃了   NSRangeException,大概是因为   该表尚未设置。

为什么表格尚未设置?你在哪种方法进行设置?

答案 4 :(得分:2)

您可以使用GCD将滚动调度到viewDidLoad中的主运行循环的下一次迭代,以实现此行为。滚动将在屏幕上显示表格视图之前执行,因此不会闪烁。

- (void)viewDidLoad {
   dispatch_async (dispatch_get_main_queue (), ^{
        NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH;
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
    }];
}

答案 5 :(得分:1)

我刚刚完成了摔跤。我在列表的顶部添加了一个搜索栏,最初隐藏在顶部... ala一些核心应用程序。我其实会问同样的问题!

我担心会提出这个问题,因为似乎那些提供服务的人会被贬低......但......我很惊讶没有一个简单的解决方案......所以我最终做到了这一点:

我使用ABTableViewCell(你可以谷歌)来自定义绘制的单元格(漂亮而快速!),当我被调用DRAW第二行时(你可以在没有ABTableViewCell的自定义绘制单元格中执行此操作),我设置它在那里,只有一个火信号量:

if ( self.mOnlyOnce == NO && theRow > 1 ) {
    self.mOnlyOnce = YES;
    [self.mParentTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

(选择适当的行/部分,适合你......如果它们在同一部分,你可能会将行设置为0以外的其他部分)

如果你讨厌我的解决方案(因为我还没有发表评论),请帮我把它留在零&让更好的解决方案登顶。

哦,还有一个关于将搜索隐藏在顶部的条目...但是我已经完成了自定义单元格...这是link

享受

答案 6 :(得分:0)

需要滚动至表格视图出现在屏幕上之前,但要在表格视图加载数据之后滚动到单元格。在viewDidLoad中使用它对我不起作用。

此代码对我来说效果很好:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    DispatchQueue.main.async { [weak self]
        let indexPath = IndexPath(row: rowIndex, section: sectionIndex)
        self?.tableView.scrollToRow(at: indexPath, at: .middle, animated: false)
    }
}

iOS 14.1 上进行了测试。

即使没有viewDidAppear,它也可以在DispatchQueue.main.async中使用,但是滚动对用户可见。我认为这不是一个好选择。

答案 7 :(得分:-1)

viewWillAppear scrollToRowAtIndexPath之前的{8}及以上版本viewDidAppear

不起作用,您必须在- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:YES]; [self.tableView reloadData]; [self.tableView scrollToRowAtIndexPath:[[NSIndexPath indexPathForRow:18 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES]; } 重新加载,如下所示:

UITableViewScrollPositionTop

注意:您必须使用scrollToRow,否则滚动将不会如预期的那样,如果您将[tableView reload]指定为最后一行,则可能会滚动到底部甚至是最后一行之后的空白区域。

我认为在iOS 8及更高版本中第一次加载tableView时它不会加载用于构造表的所有数据,这就是你必须使用IF1的原因,我认为这有点奇怪。