UITableViewCell 动态行高 + 自定义 UIView + 自动布局 [英] UITableViewCell dynamic row height + custom UIView + Auto Layout

查看:30
本文介绍了UITableViewCell 动态行高 + 自定义 UIView + 自动布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to get a custom photo container with multiple UIImageViews to fit in my tableview cell. The view contains a variable number of images (1 ~ 9), and its height would change correspondingly from 1x to 3x imageHeight.

我使用 AutoLayout 来定义带有 tableview 和自定义 UIView 的顶部/底部/前导/尾随边距,并启用自调整单元格,我设置了

I used AutoLayout to define the top/bottom/leading/trailing margins with the tableview and the custom UIView inside, and to enable self-sizing cells, I have set

tableView.estimatedRowHeight = X
tableView.rowHeight = UITableViewAutomaticDimension

我用

tableView.register(nib: forCellReuseIdentifier:)

tableView(_ tableView: cellForRowAt:) 方法中,我设置了单元格:

and in tableView(_ tableView: cellForRowAt:) method, I setup the cell with:

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

其中 setup() 使用 URL 挂钩容器中的每个 imageView

where setup() hooks each imageView in the container with a URL

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
    }
}

定义视图的内在内容大小:

Defining intrinsicContentSize for the view:

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
    }
}

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

The problem here is: after I set the initial intrinsicContentSize, the container's frame size changes in layoutSubviews() afterwards. Although by then I can position the imageView subviews correctly, the cell height will not be changed anymore.

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

Hope I am not making this problem more confusing. Could someone point out how would I resize the cell height AFTER modifying the contents of its UIView subview? Thanks!

推荐答案

这里有一些事情会导致您在使用动态大小的单元格时出现一些问题.

There are a few things here that will be causing you some issues with dynamically sized cells.

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

现在这最后一点要复杂得多.

Now this last point is alot more complicated.

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

Dynamic UITableViewCell's calculate their height based on the autolayout rules of the content within them. You MUST have enough constraints from your content to the UITableViewCell's contentView property (to all edges) that give the cell enough information to place each item, calculate its overall height and width and therefore it is able to calculate the new height.

仅使用一张图片对于动态大小的单元格来说还不错.但是在单元格最初呈现后没有任何规则地动态放置多个项目将不起作用.

Using just one image isn't too bad for dynamic sized cells. but placing multiple items dynamically without any rules after the cell has initially rendered will not work.

您需要决定这些图像在您的单元格中的布局方式.一旦你有了这个,你就可以在添加图像视图时查看添加所需的约束.就个人而言,我只会在收到每张图像后添加图像视图.

You need to decide how these images should be laid out in your cell. once you have this you can look at adding the required constraints as you add the image views. Personally I would only add the image views once i have received each image.

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

Previously when I have done this I have cached the images once received and re-loaded the cell so that the image can be placed in the cell as it is rendered, allowing the tableview cell to calculate its height based off the image dimensions and constraints.

您可能还需要考虑使用集合视图或将图像合并为单个图像并在您的单元格中使用.如果您可以访问图像,则可以在运行时或服务器端在设备上执行此操作.

You may want to also consider using a collection view or merging the images together into a single image and using that in your cell. You could do this on device at runtime or server side if you have that kind of access to the images.

这篇关于UITableViewCell 动态行高 + 自定义 UIView + 自动布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆