UITableViewCell动态行高+自定义UIView +自动布局

时间:2017-01-14 12:03:39

标签: ios objective-c swift xcode uitableview

我正在尝试获取一个包含多个UIImageViews的自定义照片容器,以适合我的tableview单元格。视图包含可变数量的图像(1~9),其高度将相应地从1x变为3x imageHeight。

我使用AutoLayout定义了tableview和自定义UIView里面的顶部/底部/前导/尾部边距,并且为了启用自定义单元格,我已经设置了

tableView.estimatedRowHeight = X
tableView.rowHeight = UITableViewAutomaticDimension

我用

初始化这些单元格
tableView.register(nib: forCellReuseIdentifier:)

并且在tableView(_ tableView: cellForRowAt:)方法中,我使用:

设置单元格
let cell = tableView.dequeueReusableCell(
    withIdentifier: "test9cell", 
               for: indexPath) as! SocialFeedTableViewCell
cell.photoContainer.setup(with: urls)
cell.photoContainer.loadImages()
return cell 

其中setup()使用URL

挂接容器中的每个imageView
func setup(with urls: [URL]) {
    self.imageUrls = urls
    for i in 0 ..< urls.count {
        let imageView = UIImageView(frame: CGRect.zero)
        self.addSubview(imageView)
        self.imageViews.append(imageView)
    }
    self.setNeedsLayout()
}

func loadImages() {
    self.imageViews.forEach { imageView in
        imageView.frame = // Calculate position for each subview
        imageView.sd_setImage(...) // Load web image asynchronously
    }
}

为视图定义intrinsicContentSize:

override var intrinsicContentSize {
    let frameWidth = self.frame.size.width
    var frameHeight: CGFloat
    switch self.imageUrls.count { // range from 1...9
    case 1...3:
        frameHeight = frameWidth / 3
    case 4...6:
        frameHeight = frameWidth / 3 * 2
    default:
        frameHeight = frameWidth
    return CGSize(frameWidth, frameHeight)
}

override func layoutSubviews() {
    super.layoutSubviews()
    self.imageViews.forEach { imageView in
        imageView.frame = // Calculate position for each subview
    }
}

这里的问题是:在我设置了初始的intrinsicContentSize之后,容器的帧大小在layoutSubviews()之后发生了变化。虽然到那时我可以正确定位imageView子视图,但不再更改单元格高度。

希望我不会让这个问题更加混乱。有人可以指出在修改其UIView子视图的内容后如何调整单元格高度?谢谢!

1 个答案:

答案 0 :(得分:0)

这里有一些事情会导致动态大小的单元格出现问题。

  1. 您正在向单元格添加多个项目,但未在图像视图上定义任何自动布局约束,因此它不知道如何正确放置/堆叠项目。
  2. 从上面的代码中你添加了一个带有CGRectZero框架的UIImageView,没有autulayout规则它们将保持为零或者在添加图像时尝试调整contentize,但它们不会调整单元格高度。
  3. 如果要从网络加载图像,则可能会在tableviewcell完成初始渲染后添加/渲染图像。因此,您可能需要缓存已加载的图像并重新加载单元格,以便它们可以在正确的时间加载。
  4. 现在最后一点更复杂了。

    动态UITableViewCell根据其中内容的自动布局规则计算其高度。你必须有足够的约束从你的内容到UITableViewCell的contentView属性(到所有边缘),它给单元格足够的信息来放置每个项目,计算它的整体高度和宽度,因此它能够计算新的高度。

    对于动态大小的单元格,仅使用一个图像并不算太糟糕。但是在单元格最初渲染后没有任何规则动态放置多个项目将不起作用。

    您需要决定如何在细胞中布置这些图像。完成后,您可以在添加图像视图时添加所需的约束。我个人只会在收到每张图片后添加图片视图。

    以前当我这样做时,我已经缓存了图像并重新加载了单元格,以便图像可以在渲染时放置在单元格中,允许tableview单元格根据图像尺寸计算其高度和约束。

    您可能还想考虑使用集合视图或将图像合并到一个图像中并在单元格中使用它。如果您具有对图像的访问权限,则可以在运行时或服务器端在设备上执行此操作。