简体   繁体   English

内在内容大小在UITableView内部的UICollectionView

[英]Intrinsic content sized UICollectionView inside UITableView

Let me preface by saying that I've spent probably 100 hours over the past few months searching Google and StackOverflow trying to answer this question. 首先,请允许我说,过去几个月来我在Google和StackOverflow上花费了100个小时来试图回答这个问题。 I've followed many tutorials and have not been able to solve my problem. 我已经阅读了许多教程,但无法解决我的问题。 Every one is a major disappointment and is disheartening. 每个人都很失望,令人沮丧。

Expectation 期望

期望

Reality 现实

现实

Problem 问题

I have a UITableView that contains a UIView. 我有一个包含UIView的UITableView。 The UIView has auto layout constraints to pin it 15pt off the edges of the cell, and then I give that a shadow and rounded corners. UIView具有自动布局约束,可将其固定在单元格边缘的15pt处,然后给它阴影和圆角。 Inside that UIView, I have a few labels, then a UICollectionView, and a stack view. 在该UIView中,我有一些标签,然后是UICollectionView和堆栈视图。

My UICollectionView keeps having a height of 0 and I can't figure out how to make it have intrinsic size. 我的UICollectionView的高度始终为0,我不知道如何使其具有固有尺寸。 The only way I can seem to make it display properly is to force a specific height to it via auto layout inside the storyboard (which is what I did to take this screenshot). 我似乎可以使其正确显示的唯一方法是,通过情节提要板中的自动布局将其强制设置为特定的高度(这就是我截取此屏幕截图的方式)。 Unfortunately, forcing a height like this is not realistic for 2 reasons: 不幸的是,由于以下两个原因,强制这样的高度是不现实的:

  1. The height varies based on the width of the device. 高度根据设备的宽度而变化。 Since the images are squares, the height is loosely (but not exactly) half the width of the device. 由于图像是正方形,因此高度大约是设备宽度的一半(但不完全是)。
  2. If there are no images, the height of the collection view should be 0. 如果没有图像,则集合视图的高度应为0。

It really seems like it should be possible to use the intrinsic content size of the flow layout here. 似乎确实可以在这里使用流布局的固有内容大小。

Storyboard 故事板

故事板

Constraints 约束

I've got about 15pt of space between each of the labels, collection view, and stack view (so, the vertical space). 每个标签,集合视图和堆栈视图之间都有大约15pt的空间(因此,垂直空间)。 The collection view prototype cell has an image view in it. 集合视图原型单元格中具有图像视图。 The image view has top, bottom, trailing and leading space all set to 0 to the collection view cell, and also has a 1:1 ratio. 图像视图的顶部,底部,尾部和前导空间到集合视图单元格都设置为0,并且比例为1:1。

Collection View Layout 集合视图布局

To achieve the layout of one large image and 4 small images, I'm using SNCollectionViewLayout . 为了实现一个大图像和4个小图像的布局,我使用了SNCollectionViewLayout

Data Source / Delegate 数据源/委托

In my controller, in viewDidLoad , I've set the estimatedRowHeight of the UITableView to 400, and I've set the rowHeight to UITableView.automaticDimension . 在我的控制器中,在viewDidLoad ,将UITableView的estimatedRowHeight viewDidLoad设置为400,并将rowHeight设置为UITableView.automaticDimension

In the tableView cellForRowAt, I dequeue a reusable custom UITableViewCell class, set various outlets on the table view cell, and call reloadData() on the collection view for the table view cell. 在tableView cellForRowAt中,我使一个可重用的自定义UITableViewCell类出队,在表视图单元格上设置各种出口,并在表视图单元格的集合视图上调用reloadData() In the storyboard, I've set the table view cell as the collection view's data source and delegate. 在情节提要中,我将表视图单元格设置为集合视图的数据源和委托。

In the table view cell's awakeFromNib function, I've got it setting the corner radius, shadow, and using the following code for the flow layout on the collection view (which you can see in their example): 在表格视图单元的awakeFromNib函数中,我已经设置了它的拐角半径,阴影,并在集合视图上使用以下代码进行流程布局(您可以在其示例中看到):

let snCollectionViewLayout = SNCollectionViewLayout()
snCollectionViewLayout.fixedDivisionCount = 4
snCollectionViewLayout.delegate = self
snCollectionViewLayout.itemSpacing = 10
collectionView.collectionViewLayout = snCollectionViewLayout

I've also implemented the optional SNCollectionViewLayoutDelegate protocol by writing the following function: 我还通过编写以下函数实现了可选的SNCollectionViewLayoutDelegate协议:

func scaleForItem(inCollectionView collectionView: UICollectionView, withLayout layout: UICollectionViewLayout, atIndexPath indexPath: IndexPath) -> UInt {
    if indexPath.row == 0 || collectionView.numberOfItems(inSection: indexPath.section) <= 2 {
        return 2
    } else {
        return 1
    }
}

This function is why the first image is twice the height and width as the rest. 这就是为什么第一张图像的高度和宽度是其余图像的两倍的原因。

Research 研究

In trying to figure this out, I've checked the collectionView.collectionViewLayout.collectionViewContentSize inside the table view cell's cellForRowAt and willDisplay methods. 为了弄清楚这一点,我检查了表格视图单元格的cellForRowAt和willDisplay方法内的collectionView.collectionViewLayout.collectionViewContentSize In either case, it's (0,0). 无论哪种情况,它都是(0,0)。

I've also tried checking it in the collection view cell's cellForItemAt and willDisplay. 我还尝试在集合视图单元格的cellForItemAt和willDisplay中对其进行检查。 Those log lines don't even print unless I add a height constraint to the collection view to force it tall, but then I don't have a good way to bring the height back down to what it should be, and any time I've tried, I got conflicting constraint warnings and really wonky stretched views (such as the stack view being totally squished). 除非我在集合视图中添加一个高度约束以使其变高,否则这些日志行甚至都不会打印,但是那时,我没有一种好方法可以在任何时候将高度降低到应该的高度。尝试过,我得到了冲突的约束警告和真正不稳定的拉伸视图(例如完全压缩了堆栈视图)。

In testing, I've forced a height constraint that's large enough for the collection view to fit, and when that happens, it renders correctly and the collection view content size is correct, so I know it's capable of keeping track (which can be seen here ). 在测试中,我强行设置了一个足以使集合视图适合的高度限制,并且当这种情况发生时,它可以正确呈现并且集合视图内容的大小正确,因此我知道它能够跟踪(可以看到) 在这里 )。

Does anyone have any insight into this? 有人对此有见识吗? I'd be happy to provide more code if you have any specifics on things to look into. 如果您有任何需要研究的细节,我很乐意提供更多代码。 I tried to give the full picture, while keeping this as short as possible (I know it's long). 我试图提供完整的图片,同时将图片尽可能的短(我知道很长)。

I feel like the issue has something to do with the collection view being inside a table view cell. 我觉得问题与表格视图单元格内的集合视图有关。

Thanks in advance. 提前致谢。

Keep a height constraint connection in your table view cell. 在表格视图单元格中保持高度约束连接。

@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!

And update the height constraint value programatically as per height calculations 并根据高度计算以编程方式更新高度限制值

self. collectionViewHeightConstraint.constant = 100 // set it to 0 if nothing to display 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM