【问题标题】:Maintain UITableView cell position with dynamic height cells after reloading source data iOS重新加载源数据iOS后使用动态高度单元格保持UITableView单元格位置
【发布时间】:2016-05-27 17:36:53
【问题描述】:

在聊天应用程序中,我在chat table view 上实现Load More 按钮。

当用户点击加载更多按钮时,旧消息(以及屏幕上显示的所有当前消息)会从数据库中获取(使用 NSFetchedResultsController),然后我在 chat table view 上调用 reloadData() 方法。

我想在重新加载表格之前将tableview的滚动位置设置为顶行。

根据消息文本,所有消息单元格的高度动态

我在故事板上使用auto layout

我的代码:

let oldContentheight = _chatTableView.contentSize.height
_chatTableView.reloadData()
executeOnMain {
    if self.firstTimeFetching {
        self.firstTimeFetching = false
        self.scrollTableToLastRow(withAnimation: false)
        //this is for going to last cell when we come to chat screen
    }
    else {
        //after pressing load more button
        let newContentHeight = self._chatTableView.contentSize.height
        let newOffset = CGPointMake(0, newContentHeight - oldContentheight)
        self._chatTableView.setContentOffset(newOffset, animated: false)
    }
}

【问题讨论】:

    标签: ios swift uitableview


    【解决方案1】:

    首先,声明属性以保存顶部可见单元格的索引路径

    @property(strong,nonatomic) *topVisibleIndexPath;
    

    然后当你点击Load More按钮时,你会得到顶部可见单元格IndexPath并保存

    NSArray *visibelIndexpaths = [yourTableView.indexPathsForVisibleRows];
    if(visibelIndexpaths.count > 0)
        self.topVisibleIndexPath = [visibelIndexpaths firstObject];
    

    重新加载后,调用方法:

    [yourTableView scrollToRowAtIndexPath:self.topVisibleIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]

    【讨论】:

    • 如果你加载的数据是附加旧数据,你应该依赖TopCell的INDEXPATH。你应该检查变量: var indexPathsForVisibleRows: [NSIndexPath]? { get } 和方法 : func scrollToRowAtIndexPath(_ indexPath: NSIndexPath, atScrollPosition scrollPosition: UITableViewScrollPosition, 动画动画: Bool)
    • 使用 var indexPathsForVisibleRows: [NSIndexPath]? { get } 获取oldIndexPath,重载后调用scroll方法滚动到原indexpath
    【解决方案2】:

    考虑使用批量更新,而不是使用reloadDatareloadData 将从您的数据源加载新元素,但它也会产生将您的滚动视图的滚动位置重置到顶部的副作用。

    你想要的是使用这个模式:

    tableView.beginUpdates()
    tableView.insertRowsAtIndexPaths([/* new rows here as an array of NSIndexPaths */], withRowAnimation: .Automatic)
    tableView.endUpdates()
    

    insertRowsAtIndexPaths 包含您要添加的新行。

    【讨论】:

    • 如果您只拨打一次insert/delete/reloadRowsAtIndexPaths,则无需使用begin/endUpdates
    • 很高兴知道,但您是否需要它才能让动态单元大小调整工作而不会抖动?
    • 是的,使用 beginUpdates/endUpdates 中间没有其他内容是更新行高的好方法。
    • 但是如何获取新获取的消息的索引路径?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多