raw*_*bee 192 ios autolayout uicollectionview uicollectionviewcell
我正在尝试UICollectionViewCells使用自动布局进行自我调整,但我似乎无法让单元格根据内容调整自己的大小.我无法理解如何根据单元格内容中的内容更新单元格的大小.
这是我尝试过的设置:
UICollectionViewCell一个UITextView.UITextView已禁用.UITextView固定在单元格左侧,显式宽度为320.UITextView固定到单元格的顶部.UITextView具有高度限制设置为其中一个恒定的UITextView报告将适合文本.这是单元格背景设置为红色,UITextView背景设置为蓝色的样子:

我把我已经在GitHub上玩的项目在这里.
Dan*_*sko 284
preferredLayoutAttributesFittingAttributes 改名为 preferredLayoutAttributesFitting
在iOS 9下看到我的GitHub解决方案中断后,我终于有时间充分调查此问题.我现在更新了repo,以包含自我调整单元格的不同配置的几个示例.我的结论是自我定型细胞在理论上很好,但在实践中却很混乱.在进行自我定型细胞时要谨慎.
TL; DR
看看我的GitHub项目
自定义单元格仅支持流程布局,因此请确保使用的是您正在使用的内容.
您需要设置两件事来使自定义单元格起作用.
systemLayoutSizeFittingSize开启systemLayoutSizeFitting设置estimatedItemSize属性后,流布局将变为动态.
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
Run Code Online (Sandbox Code Playgroud)
这有两种口味; 自动布局或自定义覆盖UICollectionViewFlowLayout.
我不会详细介绍这一点,因为有一篇关于为单元配置约束的精彩文章.只是要小心Xcode 6打破了iOS 7的一堆东西,所以,如果你支持iOS 7,你需要做的事情就像确保在单元格的contentView上设置autoresizingMask并且将contentView的边界设置为单元格的边界时细胞被加载(即estimatedItemSize).
您需要注意的事情是,您的单元格需要比表格视图单元格更严格地受到约束.例如,如果您希望宽度是动态的,那么您的单元格需要高度约束.同样,如果您希望高度是动态的,那么您需要对细胞进行宽度约束.
preferredLayoutAttributesFittingAttributes您的自定义单元格调用此函数时,您的视图已经配置了内容(awakeFromNib即已被调用).假设您的约束已经适当设置,您可以拥有这样的实现:
//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
}
Run Code Online (Sandbox Code Playgroud)
注意在iOS 9上,如果您不小心,行为会发生一些变化,可能会导致您的实施崩溃(请参阅此处).实现时,preferredLayoutAttributesFittingAttributes您需要确保只更改一次布局属性的框架.如果您不这样做,布局将无限期地调用您的实现并最终崩溃.一种解决方案是在您的单元格中缓存计算出的大小,并在您重复使用单元格时更改此值,或者像我对cellForItem属性一样更改其内容.
此时,您应该在collectionView中拥有"正常运行"的动态单元格.我在测试期间还没有找到足够的开箱即用解决方案,所以如果有的话,请随时发表评论.它仍然感觉像preferredLayoutAttributesFittingAttributes赢得动态调整恕我直言的战斗.
请注意,如果您使用原型单元格来计算estimatedItemSize - 如果您的XIB使用大小类,这将会中断.原因是当您从XIB加载单元格时,其大小类将配置为isHeightCalculated.这只会在iOS 8及更高版本上打破,因为在iOS 7上将根据设备加载大小类(iPad = Regular-Any,iPhone = Compact-Any).您可以在不加载XIB的情况下设置estimatedItemSize,也可以从XIB加载单元格,将其添加到collectionView(这将设置traitCollection),执行布局,然后将其从superview中删除.或者,您也可以让您的单元格覆盖UITableViewgetter并返回相应的特征.由你决定.
如果我错过任何事情,请告诉我,希望我帮助并祝好运编码
Mat*_*ala 43
Daniel Galasko答案的一些关键变化解决了我所有的问题.不幸的是,我没有足够的声誉直接评论(还).
在步骤1中,使用自动布局时,只需将单个父UIView添加到单元格即可.单元格内的所有内容都必须是父级的子视图.这回答了我所有的问题.虽然Xcode自动为UITableViewCells添加了这个,但它不适用于UICollectionViewCells(但它应该).根据文件:
要配置单元格的外观,请将显示数据项内容所需的视图添加为contentView属性中视图的子视图.不要直接将子视图添加到单元格本身.
然后完全跳过第3步.这不是必需的.
paw*_*221 38
在iOS10中有一个名为UICollectionViewFlowLayout.automaticSize(以前UICollectionViewFlowLayoutAutomaticSize)的新常量,所以相反:
self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)
Run Code Online (Sandbox Code Playgroud)
你可以用这个:
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
Run Code Online (Sandbox Code Playgroud)
它具有更好的性能,尤其是当您的集合视图中的单元格具有常量wid时
Mar*_*moy 30
在iOS 10+中,这是一个非常简单的两步过程.
确保所有单元格内容都放在单个UIView中(或者像UIStackView一样放在UIView的后代内部,这样可以简化自动布局).就像动态调整UITableViewCells一样,整个视图层次结构需要配置约束,从最外层容器到最内层视图.这包括UICollectionViewCell和直接子视图之间的约束
指示UICollectionView的flowlayout自动调整大小
yourFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
Run Code Online (Sandbox Code Playgroud)注意(编辑):
在Swift 4中(可能还有3个),它已被重命名为 __CODE__
kar*_*nms 12
在viewDidLoad()上添加flowLayout
override func viewDidLoad() {
super.viewDidLoad()
if let flowLayout = infoCollection.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = CGSize(width: 1, height:1)
}
}
Run Code Online (Sandbox Code Playgroud)另外,将UIView设置为您的单元格的mainContainer,并在其中添加所有必需的视图.
请参阅这个令人敬畏,令人兴奋的教程以获得进一步的参考: 在iOS 9和10中使用autolayout自动调整单元格的UICollectionView
经过一段时间的努力,我注意到如果你不禁用滚动,调整大小对UITextViews不起作用:
let textView = UITextView()
textView.scrollEnabled = false
Run Code Online (Sandbox Code Playgroud)
在一个奇怪的案例中
contentView.translatesAutoresizingMaskIntoConstraints = false
Run Code Online (Sandbox Code Playgroud)
不会工作。向 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)
])
}
}
Run Code Online (Sandbox Code Playgroud)
和往常一样
estimatedItemSize = UICollectionViewFlowLayout.automaticSize
Run Code Online (Sandbox Code Playgroud)
在 YourLayout: UICollectionViewFlowLayout
谁知道?可能会帮助某人。
https://www.vadimbulavin.com/collection-view-cells-self-sizing/
偶然发现了那里的提示 - 在有关此的所有 1000 篇文章中从未在其他任何地方看到过。
| 归档时间: |
|
| 查看次数: |
196822 次 |
| 最近记录: |