简体   繁体   English

UITableView滚动到单元格刷新的顶部

[英]UITableView Scrolls to Top on Cell Refresh

I have a UITableView with a cell that is dynamically sized to fit a UITextView inside it. 我有一个UITableView,其单元格的动态大小适合其中的UITextView。 Whenever a key is typed, the cell checks to see if the calculated height has increased, as with a newline, so it can tell the table the the cell's height needs to be recalculated. 每当键入一个键时,单元格会检查计算的高度是否增加,如换行符,因此它可以告诉表格需要重新计算单元格的高度。 I do that with this code. 我用这段代码做到了。

- (void) createNoteCellViewDidUpdate: (CreateNoteCell*) cell {

    CGFloat newHeight = [self tableView:self.tableView heightForRowAtIndexPath:CreateNoteCellIndexPath];
    if (newHeight != CGRectGetHeight(cell.contentView.frame)) {
        [self.tableView beginUpdates];
        [self.tableView endUpdates]; // <- HERE IS WHERE THE CONTENT OFFSET CHANGES
    }
}

The resize and table bounds are as expected. 调整大小和表格边界是预期的。 But instead of just animating the change in height, it also scrolls to the top. 但它不仅仅是动画高度的变化,而是滚动到顶部。 This can be seen here, when pressing the return key. 按下返回键时可以看到这一点。

表格在单元格上滚动调整大小

By Key Value Observing, I've found out that the scroll view contentOffset is being set when the scroll view's contentSize changes. 通过键值观察,我发现滚动视图的contentSize更改时正在设置滚动视图contentOffset。 And that the contentSize changes many times when the endUpdates method is called. 并且在调用endUpdates方法时,contentSize会多次更改。 When it changes it goes from a normal height, to a rather large height, then back to a normal height. 当它改变时,它从正常高度变为相当大的高度,然后回到正常高度。 I wonder if it's going to top because of that. 我想知道它是否会因此而上升。 I don't know where to go from here. 我不知道从哪里开始。

Wow, Josh Gafni's answer helped a lot; 哇,Josh Gafni的回答很有帮助; he deserves an upvote. 他应该得到一个赞成。 My solution is based off his. 我的解决方案是基于他的。 This still feels like a hack, so if anyone still has a better way to do this, I'm still very interested to hear it. 这仍然感觉像是一个黑客,所以如果有人还有更好的方法来做到这一点,我仍然很有兴趣听到它。

First I save the content offset, then I start the update. 首先我保存内容偏移量,然后开始更新。

CGPoint offset = self.tableView.contentOffset;
[self.tableView beginUpdates];
[self.tableView endUpdates];

This animates the cell's height change and adjusts all the frames to suit the constraints. 这会激活单元格的高度变化并调整所有帧以适应约束。

Next I remove all animations from the tableView's layer, so the animation to the top stops. 接下来,我从tableView的图层中删除所有动画,因此顶部的动画停止。 Then I reset the contentOffst to what it was before. 然后我将contentOffst重置为之前的状态。

[self.tableView.layer removeAllAnimations];
[self.tableView setContentOffset:offset animated:NO];

Finally, I let the tableView handle the animated scroll down so the bottom of the cell is right above the keyboard. 最后,我让tableView处理动画向下滚动,以便单元格的底部位于键盘正上方。

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

And voila, it works pretty well. 瞧,它运作得很好。

固定单元格调整大小

Here is my UITableView extension that works perfectly. 这是我的UITableView扩展,完美运行。 In Swift 2.1. 在Swift 2.1中。 Based on the accepted answer. 根据接受的答案。

extension UITableView
{
    func reloadDataAnimatedKeepingOffset()
    {
        let offset = contentOffset
        UIView.setAnimationsEnabled(false)
        beginUpdates()
        endUpdates()
        UIView.setAnimationsEnabled(true)
        layoutIfNeeded()
        contentOffset = offset
    }
}

Just a guess... 只是一个猜测......

Save the contentOffset of the uitableview before any changes. 在任何更改之前保存uitableview的contentOffset Then set it again after. 然后再设置它。

CGFloat contentOffset = self.tableView.contentOffset;

and then after the changes 然后在变化之后

self.tableView.contentOffset = contentOffset;

More simplified solution (add Notification observer when textView is changed), Swift-version. 更简化的解决方案(在更改textView时添加通知观察器),Swift版本。 Main trick is using UIView.setAnimationsEnabled . 主要技巧是使用UIView.setAnimationsEnabled

func textViewDidChanged(notification: NSNotification) {
    UIView.setAnimationsEnabled(false)

    let contentOffset = self.tableView.contentOffset

    tableView.beginUpdates()
    tableView.endUpdates()

    tableView.contentOffset = contentOffset

    UIView.setAnimationsEnabled(true)
}

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

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