我正在尝试使用自动布局来自动调整大小UICollectionViewCells
,但我似乎无法使单元格根据内容调整大小。我很难理解单元格大小是如何从单元格contentView中的内容更新的。
以下是我尝试过的设置:
UICollectionViewCell
,在其contentView中具有UITextView
。UITextView的滚动被禁用。
UITextView
固定在单元格左侧,显式宽度为320。UITextView
固定在单元格顶部。UITextView
将高度约束设置为一个常量,UITextView
报告将适合文本我把我一直在玩的项目放在GitHub上。
对Daniel Galasko的答案进行了一些关键的修改,解决了我所有的问题。不幸的是,我还没有足够的声誉来直接发表评论。
在步骤1中,当使用自动布局时,只需向单元格添加单个父UIView。单元格内的所有内容必须是父级的子视图。这回答了我所有的问题。虽然Xcode会自动为UITableViewCells添加此项,但它不会(但应该)为UICollettionViewCells添加此项。根据医生的说法:
要配置单元格的外观,请在contentView属性中将显示数据项内容所需的视图作为子视图添加到视图中。不要直接将子视图添加到单元本身。
然后完全跳过步骤3。它不需要。
在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
}
}
这个答案在iOS 14中已经过时,添加了合成布局。请考虑更新新的API
重命名为preferredLayoutAtinitesFittingAtinites并使用自动调整大小
systemLayoutSizeFittingSize
重命名为systemLayoutSizeFitting
在看到我的GitHub解决方案在iOS 9下崩溃后,我终于有时间全面调查这个问题。现在,我已经更新了repo,以包括几个用于自调整单元格大小的不同配置示例。我的结论是,自调整大小的细胞在理论上是伟大的,但在实践中是混乱的。在处理自调整大小的单元格时,请注意一点。
TL; DR
查看我的GitHub项目
自定尺寸单元格仅支持flow layout,因此请确保您使用的是自定尺寸单元格。
要使自调整大小的单元格正常工作,需要设置两件事。
#1.设置估计Itemsize
上的UICollettionViewFlowLayout
一旦您设置了estimatedItemSize
属性,流程布局将变得动态。
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
#2.添加对单元格子类大小调整的支持
这有两种风格;自动布局或自定义重写preferredLayoutAtinitesFittingAtinites
。
我不会详细讨论这个问题,因为有一篇关于配置单元格约束的精彩文章。请注意,Xcode 6破坏了iOS 7的一系列功能,因此,如果您支持iOS 7,则需要确保在单元格的contentView上设置autoresizingMask,并且在加载单元格时将contentView的边界设置为单元格的边界(即awakeFromNib
)。
您需要注意的是,您的单元格需要比表视图单元格受到更严重的约束。例如,如果希望宽度是动态的,则单元格需要高度约束。同样,如果希望高度是动态的,则需要对单元格设置宽度约束。
调用此函数时,您的视图已经配置了内容(即调用了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
}
注意:在iOS 9上,如果不小心,行为会发生一些变化,可能会导致实现崩溃(请参阅此处的更多信息)。当您实现首选布局属性fittingattributes
时,您需要确保只更改布局属性的框架一次。如果不这样做,布局将无限期地调用您的实现,并最终崩溃。一种解决方案是在单元格中缓存计算出的大小,并在重复使用单元格或更改其内容时使其无效,就像我使用isheightcomputed
属性所做的那样。
在这一点上,你应该有'运作'动态单元格在你的收藏视图。在我的测试中,我还没有找到足够的开箱即用的解决方案,所以如果你有,请随时发表评论。感觉仍然像UITableView
赢得了动态大小的战斗。
##注意事项非常注意,如果你使用原型单元格来计算估计的Itemsize-如果你的XIB使用size类,这将被打破。这样做的原因是,当您从XIB加载单元格时,它的大小类将配置为未定义的
。这只会在iOS8及以上打破,因为在iOS7大小类将加载基于设备(iPad=常规-任何,iPhone=紧凑型-任何)。您可以设置估计的Itemsize而不加载XIB,或者您可以从XIB加载单元格,将其添加到集合视图(这将设置traitCollection),执行布局,然后将其从超级视图中删除。或者,您也可以让您的单元格覆盖traitCollection
getter并返回相应的特征。这取决于你。
如果我错过了什么,请告诉我,希望我能帮助你,祝你好运
我知道如何在UITableView中制作UITableViewCell自身大小。问题是如何只制作特定的单元格自身大小。我的表中有四个不同的自定义UITableView单元格,我想只制作一个单元格自身大小。
我试图用swXXXdp布局文件为不同的屏幕大小创建不同的布局。不幸的是,我仍然不能分开5,0“和6,3”作为可见的附上的图像。两种大小仍然使用相同的文件:layout-sw412dp。对此有什么想法吗?
对于我的表视图单元格的动态高度,我从此链接中引用。在 UITableView 中使用自动布局进行动态单元格布局 这是我的表视图数据源和委托方法的代码 我有 2 个问题: > 我的问题是我在线路附近收到错误 在和。 为什么我必须在单元格中同时写入标签文本“和? 另外,我是否缺少实现单元动态高度所需的任何内容?
我有一个典型的主细节应用程序,它允许用户浏览对象的滚动列表,然后通过推送序列钻取任何特定对象的细节。滚动主列表是使用原型单元构建的UITableView,详细场景是具有固定数量的部分和单元的静态UITableView。 我想在我的应用程序中实现动态类型和自动调整单元格大小,以便用户可以更改基本字体大小。到目前为止,我已经成功地使用原型单元格的滚动列表制作了自定大小的单元格:使用Auto Layou
我正在用Swift设计iOS应用程序,而不是使用自动布局。我没有使用自动布局,因为如果使用自动布局,当标签更新时,设计会重置。目前,我正在设计一款4.7英寸的iPhone,但当我在任何其他尺寸的设备的模拟器上运行它时,设计完全是一团糟。 更新: 我用适当的约束设计了我的故事板。我在override func ViewDidLayoutSubView中添加了UIImages,并将其放置在屏幕之外。当
我应该添加哪些约束来设置宽度和高度与Superview成比例(在我的例子中是UIViewController的视图)在iOS自动布局中,通过自动调整大小,我们可以像下面显示的图片一样进行操作。