我试图得到自我大小UICollectionViewCells工作与自动布局,但我似乎不能让单元格大小自己的内容。我很难理解如何从单元格的contentView内的内容更新单元格的大小。

下面是我尝试过的设置:

自定义UICollectionViewCell,在它的contentView中有一个UITextView。 UITextView的滚动被禁用。 contentView的水平约束是:"H:|[_textView(320)]",也就是说UITextView被固定在单元格的左边,显式宽度为320。 contentView的垂直约束是:"V:|-0-[_textView]",也就是说UITextView固定在单元格的顶部。 UITextView有一个高度约束设置为常数,UITextView报告将适合文本。

下面是单元格背景设置为红色,UITextView背景设置为蓝色时的效果:

我把我一直在GitHub上玩的项目放在这里。


当前回答

在iOS10中有一个名为UICollectionViewFlowLayout的新常量。automaticSize(以前的UICollectionViewFlowLayoutAutomaticSize),所以改为:

self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)

你可以用这个:

self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

它具有更好的性能,特别是当集合视图中的单元格具有恒定宽度时。

访问流布局:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
   }
}

Swift 5更新:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    }
}

其他回答

在iOS10中有一个名为UICollectionViewFlowLayout的新常量。automaticSize(以前的UICollectionViewFlowLayoutAutomaticSize),所以改为:

self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)

你可以用这个:

self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

它具有更好的性能,特别是当集合视图中的单元格具有恒定宽度时。

访问流布局:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
   }
}

Swift 5更新:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    }
}

在Swift 5中,它适用于我。

UICollectionViewFlowLayout:

estimatedItemSize = UICollectionViewFlowLayout.automaticSize

UICollectionViewCell:

(ps:我用的是SnapKit)

class Cell: UICollectionViewCell {
    let customizedContentView = UIView()
    ...
    func layoutAction() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(customizedContentView)
        customizedContentView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
}

然后你只需要展开customizedContentView。

如果你实现uicollectionviewdelegatflowlayout方法:

- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath*)indexPath

当你调用collectionview performBatchUpdates:completion:时,size height将使用sizeForItemAtIndexPath代替 preferredLayoutAttributesFittingAttributes。

performBatchUpdates:completion的呈现过程将通过preferredLayoutAttributesFittingAttributes方法,但它会忽略您的更改。

内容查看主播奥秘:

在一个奇怪的例子中

    contentView.translatesAutoresizingMaskIntoConstraints = false

不会起作用。在contentView中添加了四个显式的锚,它工作了。

class AnnoyingCell: UICollectionViewCell {
    
    @IBOutlet var word: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame); common() }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder); common() }
    
    private func common() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            contentView.leftAnchor.constraint(equalTo: leftAnchor),
            contentView.rightAnchor.constraint(equalTo: rightAnchor),
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}

像往常一样

    estimatedItemSize = UICollectionViewFlowLayout.automaticSize

在你的布局:UICollectionViewFlowLayout

谁知道呢?也许能帮到别人。

信贷

https://www.vadimbulavin.com/collection-view-cells-self-sizing/

无意中发现了这个技巧——在其他1000篇文章中从未见过。

除了以上答案,

只要确保你将UICollectionViewFlowLayout的estimatedItemSize属性设置为某个大小,而不实现sizeForItem:atIndexPath委托方法。

就是这样。