UITableview 在重新加载时滚动到顶部
UITableview Scrolls to Top on Reload
我的应用程序出现问题 - 您可以 post 并编辑您最喜欢的地方。 post编辑 post 或编辑特定 post (UITableViewCell
) 后,UITableview
会重新加载。
我的问题是:UITableview
重新加载后滚动到顶部。但这不是我想要的。我希望我的视图停留在我所在的单元格/视图上。但我不知道如何管理它。
你能帮帮我吗?
UITableView
的 reloadData()
方法明确地强制重新加载整个 tableView。它运行良好,但如果您要使用用户当前正在查看的表视图来执行此操作,通常会令人不快且用户体验不佳。
相反,请查看 reloadRowsAtIndexPaths(_:withRowAnimation:)
和
reloadSections(_:withRowAnimation:)
in the documentation。
为了防止滚动到顶部,您应该在加载时保存单元格的高度,并在 tableView:estimatedHeightForRowAtIndexPath
:
中给出准确的值
// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary;
// initialize it in ViewDidLoad or other place
cellHeightsDictionary = @{}.mutableCopy;
// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
}
// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
if (height) return height.doubleValue;
return UITableViewAutomaticDimension;
}
如果您使用可动态调整大小的单元格 (UITableViewAutomaticDimension),Igor 的答案是正确的
这里是 swift 3:
private var cellHeights: [IndexPath: CGFloat?] = [:]
var expandedIndexPaths: [IndexPath] = []
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cellHeights[indexPath] {
return height ?? UITableViewAutomaticDimension
}
return UITableViewAutomaticDimension
}
func expandCell(cell: UITableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
if !expandedIndexPaths.contains(indexPath) {
expandedIndexPaths.append(indexPath)
cellHeights[indexPath] = nil
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
//tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
}
}
在swift3.1
DispatchQueue.main.async(execute: {
self.TableView.reloadData()
self.TableView.contentOffset = .zero
})
如果你想要一个简单的解决方案,就选择这些行
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.setContentOffset(contentOffset, animated: false)
现在 swift 5 我们可以用一个简单的 tableview.reloadDataAndKeepOffset()
我的应用程序出现问题 - 您可以 post 并编辑您最喜欢的地方。 post编辑 post 或编辑特定 post (UITableViewCell
) 后,UITableview
会重新加载。
我的问题是:UITableview
重新加载后滚动到顶部。但这不是我想要的。我希望我的视图停留在我所在的单元格/视图上。但我不知道如何管理它。
你能帮帮我吗?
UITableView
的 reloadData()
方法明确地强制重新加载整个 tableView。它运行良好,但如果您要使用用户当前正在查看的表视图来执行此操作,通常会令人不快且用户体验不佳。
相反,请查看 reloadRowsAtIndexPaths(_:withRowAnimation:)
和
reloadSections(_:withRowAnimation:)
in the documentation。
为了防止滚动到顶部,您应该在加载时保存单元格的高度,并在 tableView:estimatedHeightForRowAtIndexPath
:
// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary;
// initialize it in ViewDidLoad or other place
cellHeightsDictionary = @{}.mutableCopy;
// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
}
// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
if (height) return height.doubleValue;
return UITableViewAutomaticDimension;
}
如果您使用可动态调整大小的单元格 (UITableViewAutomaticDimension),Igor 的答案是正确的
这里是 swift 3:
private var cellHeights: [IndexPath: CGFloat?] = [:]
var expandedIndexPaths: [IndexPath] = []
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cellHeights[indexPath] {
return height ?? UITableViewAutomaticDimension
}
return UITableViewAutomaticDimension
}
func expandCell(cell: UITableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
if !expandedIndexPaths.contains(indexPath) {
expandedIndexPaths.append(indexPath)
cellHeights[indexPath] = nil
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
//tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
}
}
在swift3.1
DispatchQueue.main.async(execute: {
self.TableView.reloadData()
self.TableView.contentOffset = .zero
})
如果你想要一个简单的解决方案,就选择这些行
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.setContentOffset(contentOffset, animated: false)
现在 swift 5 我们可以用一个简单的 tableview.reloadDataAndKeepOffset()