我试图通过自动布局来调整UICollectionViewCells个单元格的大小,但我似乎无法使单元格根据内容调整大小.我很难理解如何根据单元格contentView中的内容更新单元格大小.

以下是我try 过的设置:

  • 自定义UICollectionViewCell,其内容视图中包含UITextView.
  • UITextView的滚动被禁用.
  • contentView的水平约束是:"H:|[_textView(320)]",即UITextView固定在单元格左侧,显式宽度为320.
  • contentView的垂直约束为:"V:|-0-[_textView]",即固定在单元格顶部的UITextView.
  • UITextView的高度约束设置为一个常数,UITextView个报告将适合文本.

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

我把我一直在玩的项目放在GitHubhere上.

推荐答案

这个答案在IOS 14中已经过时,因为增加了构图布局.请考虑更新new API

Updated for Swift 5

preferredLayoutAttributesFittingAttributes重命名为preferredLayoutAttributesFitting并使用自动调整大小


Updated for Swift 4

systemLayoutSizeFittingSize重命名为systemLayoutSizeFitting


Updated for iOS 9

在看到我的GitHub解决方案在iOS9下崩溃后,我终于有时间全面调查这个问题了.我现在已经更新了repo,包括了几个用于自调整单元大小的不同配置的示例.我的结论是,自调整细胞大小在理论上是伟大的,但在实践中却是混乱的.在继续调整单元格大小时需要注意的一点是.

TL;DR

看看我的GitHub project美元


只有流布局才支持自调整单元格大小,因此请确保您使用的是自调整大小的单元格.

要使单元格自调整大小正常工作,需要设置两项内容.

#1.将estimatedItemSize设置为UICollectionViewFlowLayout

一旦设置了estimatedItemSize属性,流布局本质上就会变成动态的.

self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

#2.添加对计算单元格子类大小的支持

这有两种口味;自动布局or自定义覆盖preferredLayoutAttributesFittingAttributes.

使用自动布局创建和配置单元格

我不会详细介绍这一点,因为有关于为单元配置约束的精彩的SO post篇文章.只需小心Xcode 6 broke和iOS7中的一堆东西,所以,如果你支持iOS7,你将需要做一些事情,比如确保在单元格的contentView上设置了autosizingMask,并且在加载单元格时(即awakeFromNib)将contentView的边界设置为单元格的边界.

您需要注意的是,您的单元格需要比表视图单元格受到更严格的约束.例如,如果希望宽度是动态的,则单元格需要高度约束.同样,如果希望高度是动态的,则需要对单元格进行宽度约束.

Implement preferredLayoutAttributesFittingAttributes in your custom cell

当调用此函数时,您的视图已经配置了内容(即调用了cellForItem).假设您的约束设置得当,您可以有一个如下所示的实现:

//forces the system to do one layout pass
var isHeightCalculated: Bool = false

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    //Exhibit A - We need to cache our calculation to prevent a crash.
    if !isHeightCalculated {
        setNeedsLayout()
        layoutIfNeeded()
        let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
        var newFrame = layoutAttributes.frame
        newFrame.size.width = CGFloat(ceilf(Float(size.width)))
        layoutAttributes.frame = newFrame
        isHeightCalculated = true
    }
    return layoutAttributes
}

NOTE在iOS9上,行为稍有改变,如果您一不小心,可能会导致您的实现崩溃(参见更多here页).在实现preferredLayoutAttributesFittingAttributes时,您需要确保只更改布局属性的框架一次.如果您不这样做,布局将无限期地调用您的实现,最终导致崩溃.一种解决方案是将计算出的大小缓存在单元格中,并在任何时候重用单元格或更改其内容时使其无效,就像我对isHeightCalculated属性所做的那样.

体验您的布局

此时,您的集合视图中应该有"正常运行"的动态单元格.在我的测试过程中,我还没有发现足够的开箱即用的解决方案,所以如果您有,请随意 comments .它仍然感觉UITableView赢得了动态大小之战IMHO.

##注意事项 请非常注意,如果您使用原型单元格来计算EstiatedItemSize-如果您的值为XIB uses size classes,这将中断.这样做的原因是,当您从XIB加载单元时,其Size类将配置为Undefined.这只会在iOS8和更高版本上被打破,因为在iOS7上,Size类将根据设备加载(iPad=Regular-Any,iPhone=Compact-Any).您可以在不加载XIB的情况下设置EstiatedItemSize,也可以从XIB加载单元格,将其添加到集合视图(这将设置traitCollection),执行布局,然后将其从SuperView中删除.或者,您也可以让您的计算单元覆盖traitCollection获取函数并返回适当的特征.由你决定.

如果我错过了什么,请告诉我,希望我能帮助你,祝你好运


Ios相关问答推荐

Xcode15.3上的生成错误:调用的对象类型';facebook::flipper::SocketCertificateProvider';不是函数或函数指针

如何在Flutter 中为S家长增加一个相对高度的间距

在将Cocoapods更新到1.13.0之后,它抛出错误

无法向委托发送数据

Swift Vision库识别文本后如何将其赋值给 struct 体实例属性以供显示?

如果使用 .onAppear 设置,为什么 SwiftUI Picker 不显示正确的选定值

一对多关系 Firebase 实时数据库(嵌入数百万条 comments )

iOS 16 堆栈视图中按钮的奇怪动画

Swiftui为什么在点击第二行之前背景不起作用

在所有 tableview / collectionview 中禁用滚动指示器

按钮在 SwiftUI 中没有采用给定的高度和宽度

实现一个将块用作回调的方法

SwiftUI 视图 - viewDidLoad()?

没有 Mac 的 Xamarin Visual Studio IOS 开发?

如何在 iOS 中判断暗模式?

Xcode:此时无法安装此应用程序.

NSPredicate 用于测试 NULL 和空白字符串

水平滚动 UICollectionView 时对齐单元格的中心

SLComposeViewController 分享教程

如果我的分发证书过期会怎样?