scrollToRowAtIndexPath没有正确处理最后一行

时间:2014-03-14 13:14:43

标签: ios iphone objective-c uitableview user-interface

我遇到UITableView的问题,在使用scrollToRowAtIndexPath:atScrollPosition:animated时,它似乎无法正确滚动到最后一行

这是我用来导致滚动的代码:

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

这是显示结果的屏幕截图(和问题!):

UITableView scroll issue screenshot

如您所见,最后一行( 9月)未完全滚动到视图中;底部几个像素被切断。

我尝试使用UITableViewScrollPositionNoneUITableViewScrollPositionTopUITableViewScrollPositionBottom作为滚动位置,但它们都会产生相同的结果。

我的单元格确实具有61.0f的自定义单元格高度,该高度当前在故事板中设置,但添加UITableViewDelegate方法tableView:heightForRowAtIndexPath:并返回相同的值也无济于事。

有什么方法可以让表格视图滚动到最后一行 AND 让它完全可见?

修改

为了清楚起见,我正在使用股票UINavigationController和股票UITableViewController作为根视图控制器。

编辑2:

如果我使用rectForRowAtIndexPath:来确定行的rect,它实际上会返回该行的正确rect。但是,如果我然后使用该矩形调用scrollRectToVisible:animated:,我得到与上面相同的结果;最后几个像素被切断了。

4 个答案:

答案 0 :(得分:27)

好的,我已经成功解决了这个问题。

comment Matt Di Pasquale对半相关问题提出了线索。

事实证明,在iOS 7中,当调用viewWillAppear:时,视图尚未布局,这意味着表视图的框架和边界不能保证准确。由于对scrollToRowAtIndexPath:animated的调用必须至少使用其中一个来计算偏移量,因此在我的情况下,为什么没有正确处理它是有道理的。

我认为在大多数情况下,人们不会遇到这个问题,因为他们的呈现视图控制器可能与呈现的视图控制器具有相同的界限。但在我的情况下,我提出了一个视图控制器,它有一个可见的导航栏和一个没有任何一个的状态栏,而且还有额外的64分。在此控制台输出中可以看到:

2014-03-15 19:14:32.129 Capture[3375:60b] viewWillAppear, tv bounds: {{0, 0}, {320, 568}}
2014-03-15 19:14:32.131 Capture[3375:60b] viewDidLayoutSubviews, tv bounds: {{0, -64}, {320, 568}}

要解决此问题,我现在在viewWillAppear:设置一个标志,表示有待处理的滚动,然后在viewDidLayoutSubviews,如果设置了标记,我会调用scrollToRowAtIndexPath:animated并取消设置标志(,因为此方法被多次调用)。这完美无缺。

希望这可以帮助其他任何人解决这个问题。

答案 1 :(得分:2)

使用较低级别的功能怎么样?毕竟,UITableViewUIScrollView

[self.tableView setContentOffset:(CGPoint){0, self.tableView.contentSize.height - self.tableView.bounds.size.height} animated:YES];

(如果内容边缘插入不是0,则根据需要调整偏移量。)

答案 2 :(得分:0)

当用户触摸后退按钮时,当我滚动到tableView的特定行时,我注意到了同样的错误。我注意到表格视图的contentInset在导航期间正在发生变化(由于automaticallyAdjustsScrollViewInsets = true)。我找到的唯一解决方案是添加一个观察者:

tableView.addObserver(self, forKeyPath: "contentInset", options: .new, context: nil)

并在scrollToRow建立之后执行contentInset方法。这不是一个漂亮的解决方案,但它确实有效。

答案 3 :(得分:-1)

我还建议你打开一个UIViewController属性,默认情况下处于启用状态:

@property (nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets;

当我不知道为什么UITableView(实际上是UIScrollView的子类)没有正确滚动时,这个问题帮助了我很多问题。根据您的课程布局而定。

此属性自iOS 7开始提供,请在此处详细了解:

http://b2cloud.com.au/general-thoughts/uiviewcontroller-changes-in-ios7