![](/img/trans.png)
[英]Reload constraint or update height in self-sizing tableview cell after image is downloaded
[英]How to update tableview cell height after image downloaded and height constraint changed swift?
更新异步下载图像的图像高度约束后如何更新tableview单元格高度?
图像下载和约束更改后如何触发tableView单元格重新布局?
这样做的最佳方法是什么?
已经尝试将代码放入 Dispatch 主队列,但结果同样糟糕。 我在 cellForRow 方法中这样做,也将它移动到 willDisplayCell。 一次又一次这个问题...
使用 Kingfisher 库进行图像缓存的代码示例:
if let imgLink = post.imageLink {
if let url = URL(string: imgLink) {
cell.postImage.kf.setImage(with: url, placeholder: UIImage(), options: nil, progressBlock: nil) { (image, error, cacheType, imageURL) in
if let image = image, cell.tag == indexPath.row {
cell.heightConstraint.constant = image.size.height * cell.frame.size.width / image.size.width
}
}
}
}
您可以尝试调用这 2 行以在图像可用后重新计算单元格高度:
tableView.beginUpdates()
tableView.endUpdates()
请参阅文档https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates :“您还可以使用此方法后跟 endUpdates() 方法来为行高的变化设置动画,而无需重新加载单元格.”
恕我直言,正如ppalancica 指出的那样,调用 beginUpdates 和 endUpdates 是理想的方式。 您不能从 UITableViewCell 内部引用 tableView,正确的方法是使用委托并从实现委托的 ViewController 调用 beginUpdates 和 endUpdates。
代表:
protocol ImageCellDelegate {
func onLayoutChangeNeeded()
}
UITableViewCell 实现:
class ImageCell: UITableViewCell {
var imageView: UIImageView = ...
var delegate: ImageCellDelegate?
...
func setImage(image: UIImage) {
imageView.image = image
//calling delegate implemented in 'ViewController'
delegate?.onLayoutChangeNeeded()
}
...
}
视图控制器实现:
class ViewController: UIViewController, UITableViewDataSource, ImageCellDelegate {
var tableView: UITableView = ...
.....
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let imageCell = tableView.dequeueReusableCell(withIdentifier: id, for: indexPath) as! ImageCell
//setting 'delegate' here
imageCell.delegate = self
return imageCell
}
//called from 'ImageCell' when 'image' is set inside 'setImage'
func onLayoutChangeNeeded() {
tableView.beginUpdates()
tableView.endUpdates()
}
.....
}
我有同样的问题。 您需要记住的是 Tableview 重用单元格并且您正在异步加载图像。
推荐:您可以要求您的反手团队为您提供图像的高度和宽度,以便您计算单元格高度并尽快返回。
如果您不能这样做,您可以在数据源中保留下载图像的大小。 因此,在下载图像之前,请检查数据源的图像大小并更新高度约束常量。
另一件事是你应该在 cellForRow 和 willDisplay 单元格中都这样做(我知道这不是一个好习惯,但要满足 tableview 自动维度)
更新高度常量后,您应该使用这对代码重新加载您的单元格。
cell.setNeedsLayout()
cell.layoutIfNeeded()
我是怎么做的
if let imagesize = post.imageSize {
cell.updateHeightPerRatio(with: imagesize)
} else {
// Here load size from URL and update your datasource
}
// Load image from URL with any SDWebimage or any other library you used
我实际所做和以某种方式工作的内容如下:
if (self.firstLoaded[indexPath.row] == false) {
self.firstLoaded[indexPath.row] = true
DispatchQueue.main.async {
self.tableViewController.tableView.reloadData()
}
}
firstLoaded 只是告诉表这一行已经从 URL 接收到图像并计算/存储了正确的高度。
另外,我使用了这个:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cellHeights[indexPath] {
return height
}
return 1500
}
我知道调用 reloadData() 不是一个好习惯,但它解决了我的问题。 如果有人有其他建议,请不要犹豫,分享。
谢谢!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.