使用 UITableViewAutomaticDimension 将 UITableViewCell 更新到位后生涩滚动 [英] Jerky Scrolling After Updating UITableViewCell in place with UITableViewAutomaticDimension
问题描述
我正在构建一个应用程序,该应用程序具有用户提交的帖子的提要视图.这个视图有一个带有自定义 UITableViewCell
实现的 UITableView
.在这个单元格内,我有另一个 UITableView
用于显示注释.要点是这样的:
I am building an app that has a feed view for user-submitted posts. This view has a UITableView
with a custom UITableViewCell
implementation. Inside this cell, I have another UITableView
for displaying comments. The gist is something like this:
Feed TableView
PostCell
Comments (TableView)
CommentCell
PostCell
Comments (TableView)
CommentCell
CommentCell
CommentCell
CommentCell
CommentCell
初始提要将下载 3 条评论供预览,但如果有更多评论,或者用户添加或删除评论,我想更新提要内的 PostCell
通过在 PostCell
内的评论表中添加或删除 CommentCells
来实现表格视图.我目前正在使用以下帮助程序来完成该任务:
The initial feed will download with 3 comments for previewing, but if there are more comments, or if the user adds or deletes a comment, I want to update the PostCell
in place inside of the feed table view by adding or removing CommentCells
to the comments table inside of the PostCell
. I am currently using the following helper to accomplish that:
// (PostCell.swift) Handle showing/hiding comments
func animateAddOrDeleteComments(startRow: Int, endRow: Int, operation: CellOperation) {
let table = self.superview?.superview as UITableView
// "table" is outer feed table
// self is the PostCell that is updating it's comments
// self.comments is UITableView for displaying comments inside of the PostCell
table.beginUpdates()
self.comments.beginUpdates()
// This function handles inserting/removing/reloading a range of comments
// so we build out an array of index paths for each row that needs updating
var indexPaths = [NSIndexPath]()
for var index = startRow; index <= endRow; index++ {
indexPaths.append(NSIndexPath(forRow: index, inSection: 0))
}
switch operation {
case .INSERT:
self.comments.insertRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.None)
case .DELETE:
self.comments.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.None)
case .RELOAD:
self.comments.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.None)
}
self.comments.endUpdates()
table.endUpdates()
// trigger a call to updateConstraints so that we can update the height constraint
// of the comments table to fit all of the comments
self.setNeedsUpdateConstraints()
}
override func updateConstraints() {
super.updateConstraints()
self.commentsHeight.constant = self.comments.sizeThatFits(UILayoutFittingCompressedSize).height
}
这样就可以很好地完成更新了.该帖子会按预期在 PostCell
内添加或删除评论就地更新.我在提要表中使用自动调整大小 PostCells
.PostCell
的评论表展开以显示所有评论,但动画有点生涩,并且表格在单元格更新动画发生时上下滚动十几个像素左右.
This accomplishes the update just fine. The post is updated in place with comments added or removed inside of the PostCell
as expected. I am using auto sizing PostCells
in the feed table. The comments table of the PostCell
expands to show all of the comments, but the animation is a bit jerky and the table sort of scrolls up and down a dozen pixels or so while the cell update animation takes place.
调整大小时的跳跃有点烦人,但我的主要问题是后来出现的.现在,如果我在提要中向下滚动,滚动会像以前一样平滑,但是如果我在添加评论后刚刚调整大小的单元格上方向上滚动,提要会在到达提要顶部之前向后跳几次.我为 Feed 设置 iOS8
自动调整大小的单元格,如下所示:
The jumping during resizing is a bit annoying, but my main issue comes afterwards. Now if I scroll down in the feed, the scrolling is smooth as before, but if I scroll up above the cell I just resized after adding comments, the feed will jump backwards a few times before it reaches the top of the feed. I setup iOS8
auto sizing cells for the Feed like this:
// (FeedController.swift)
// tableView is the feed table containing PostCells
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 560
如果我删除 estimatedRowHeight
,表格只会在单元格高度发生变化时滚动到顶部.我现在对此感到很困惑,作为一名新的 iOS 开发者,可以使用您可能拥有的任何技巧.
If I remove the estimatedRowHeight
, the table just scrolls to the top anytime a cell height changes. I'm feeling pretty stuck on this now and as a new iOS developer, could use any tips you might have.
推荐答案
这是我找到的解决此类问题的最佳方案(滚动问题 + reloadRows + iOS 8 UITableViewAutomaticDimension);
Here is the best solution I found to solve this kind of problem (scrolling problem + reloadRows + iOS 8 UITableViewAutomaticDimension);
它包括将每个高度保存在字典中并更新它们(在字典中),因为 tableView 将显示单元格.
It consists by keeping every heights in a dictionary and updating them (in the dictionary) as the tableView will display the cell.
然后您将在 - (CGFloat)tableView:(UITableView *)tableView EstimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
方法中返回保存的高度.
You will then return the saved height in - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
method.
你应该实现这样的东西:
You should implement something like this :
目标 C
- (void)viewDidLoad {
[super viewDidLoad];
self.heightAtIndexPath = [NSMutableDictionary new];
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = [self.heightAtIndexPath objectForKey:indexPath];
if(height) {
return height.floatValue;
} else {
return UITableViewAutomaticDimension;
}
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = @(cell.frame.size.height);
[self.heightAtIndexPath setObject:height forKey:indexPath];
}
Swift 3
@IBOutlet var tableView : UITableView?
var heightAtIndexPath = NSMutableDictionary()
override func viewDidLoad() {
super.viewDidLoad()
tableView?.rowHeight = UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = heightAtIndexPath.object(forKey: indexPath) as? NSNumber {
return CGFloat(height.floatValue)
} else {
return UITableViewAutomaticDimension
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let height = NSNumber(value: Float(cell.frame.size.height))
heightAtIndexPath.setObject(height, forKey: indexPath as NSCopying)
}
这篇关于使用 UITableViewAutomaticDimension 将 UITableViewCell 更新到位后生涩滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!