【问题标题】:UITableview Scrolls to Top on ReloadUITableview 在重新加载时滚动到顶部
【发布时间】:2016-10-03 13:16:11
【问题描述】:

我在我的应用程序中遇到问题 - 您可以发布和编辑您最喜欢的地方。发布帖子或编辑特定帖子 (UITableViewCell) 后,UITableview 会重新加载。

我的问题是:UITableview 重新加载后滚动到顶部。但这不是我想要的。我希望我的视图停留在我所在的单元格/视图上。但我不知道如何管理它。

你能帮帮我吗?

【问题讨论】:

  • 你看过UITableView的方法吗:reloadRowsAtIndexPaths
  • 看看这个答案stackoverflow.com/questions/28043632/… 你可能需要在重新加载时保存正在查看的索引才能知道滚动到哪里

标签: swift tableview cell reloaddata


【解决方案1】:

如果您使用可动态调整大小的单元格 (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)
        }
      }
    }

【讨论】:

  • 令人惊讶的是这有帮助,而且我没有使用动态单元格高度。谢谢!
  • 是的,当您以编程方式添加动态行高时,此代码很有用。我正在从 textview 文本计算行高。重新加载 tableview 时出现小凹凸。添加此代码将消除那个小凸起。
  • expandCell() 方法的目的是什么,我看不懂。它只是为了演示还是我需要在我的代码中使用它?
【解决方案2】:

为防止滚动到顶部,您应该在加载单元格时保存它们的高度,并在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;
}

【讨论】:

  • 这行得通,但你能解释一下为什么 heightForRowAt 还不够吗?
  • 这适用于底部滚动时的表格视图。但在顶部滚动的情况下不起作用。您能否提出一些建议,究竟是什么问题?
  • 您是指以编程方式滚动到某个 indexPath 并跳过一些第一行的情况吗?如果是,那么您可以预先计算高度。
  • 面临与@Gautam Shrivastav 相同的问题,当滚动到顶部并在顶部加载新行时,它会自动滚动到新数据的顶部,而不是应该保留在最后一个可见单元格上。
【解决方案3】:

UITableViewreloadData() 方法明确地强制重新加载整个 tableView。它运行良好,但如果您要使用用户当前正在查看的 tableview 来执行此操作,通常会令人不快且用户体验不佳。

相反,请查看 reloadRowsAtIndexPaths(_:withRowAnimation:) reloadSections(_:withRowAnimation:) in the documentation

【讨论】:

  • 这两种方法有时都会触发完全重新加载。
【解决方案4】:

如果你想要一个简单的解决方案,就去这些行

let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.setContentOffset(contentOffset, animated: false)

【讨论】:

    【解决方案5】:

    在 Swift 3.1 中

    DispatchQueue.main.async(execute: {
    
        self.TableView.reloadData()
        self.TableView.contentOffset = .zero
    
    })
    

    【讨论】:

    • @OsamaBinBashir 不是真的,但你必须在主线程上调用这个方法。
    • @EduardoIrias 同意这一点:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2010-10-18
    • 2015-07-18
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多