如何正确调整UICollectionView的大小以使其完全显示其内容?我尝试了很多东西,包括设置框架,调用reloadData
并使布局无效:
self.collectionView.contentSize = CGSizeMake(300, 2000);
self.collectionView.frame = CGRectMake(0, 0, 300, 2000);
[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];
但这些都没有任何影响。按下按钮后,我仍然可以看到初始视图,如下所示:
我有一个小型的演示程序,我有一个产生100个元素的数据源。在Interface Builder中,我最初将UICollectionView的大小设置为一个较小的值,以便不是所有元素都适合,之后我按下一个按钮,然后执行上面的代码。我希望UICollectionView现在显示所有元素,但它不会。
编辑: 可以在https://github.com/mjdemilliano/TestUICollectionView找到演示程序。
EDIT2: 我观察到帧更新在某些时候丢失,因为如果我再次按下按钮,当前帧将返回到旧的价值。在按钮事件处理程序中添加一些日志语句后,日志输出为:
before: frame = {{0, 58}, {320, 331}}, contentSize = {320, 1190}
update button pressed
after: frame = {{0, 0}, {300, 2000}}, contentSize = {300, 2000}
before: frame = {{0, 58}, {320, 331}}, contentSize = {320, 1190}
update button pressed
after: frame = {{0, 0}, {300, 2000}}, contentSize = {300, 2000}
我不明白为什么不保留帧更改,更改它的是什么。
在某些时候,我会用流布局中获得的值替换硬编码值,但我想排除这一点,并尽可能保持我的示例。
上下文:我最终想要做的是:我有一个可滚动的视图,包含标签和图像等各种控件,以及一个包含动态内容的集合视图。我想滚动所有这些,而不仅仅是集合视图,因此我没有使用集合视图自己的滚动工具,它工作正常。
答案 0 :(得分:103)
我最终通过修复所有自动布局问题,使用约束修复集合视图的高度来解决这个问题。然后,每当我知道内容已更改时,我使用值collectionView.contentSize.height
:
self.verticalLayoutConstraint.constant = self.collectionView.contentSize.height;
然后正确调整集合视图的大小,它在整个scrollview中表现良好。我已经用我的更改更新了GitHub测试项目。
对我来说,通过手动更新约束而不是告诉iOS来做到这一点:“使集合视图的框架高度尽可能大”对我来说感觉不对,但它是最好的我到目前为止已经提出来了。如果你有答案,请发一个更好的答案。
答案 1 :(得分:2)
UICollectionViewFlowLayout *flowLayout;
flowLayout = [[UICollectionViewFlowLayout alloc]init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[flowLayout setMinimumInteritemSpacing:0.0f];
[flowLayout setMinimumLineSpacing:0.0f];
[self.collectionView setPagingEnabled:NO];
[flowLayout setItemSize:CGSizeMake(322.0, 148.0)]; //important to leave no white space between the images
[self.collectionView setCollectionViewLayout:flowLayout];
我发现故事板中的自动布局并没有太大帮助。您的collectionView的UICollectionViewFlowLayout的正确设置是真正的帮助。如果使用setItemSize调整项目大小,则可能会得到所需的结果。
答案 2 :(得分:2)
这是一种通过其内在大小绑定CollectionView高度的方法。 我用它在TableView Cell中正确调整CollectionView的大小(动态单元格高度)。而且效果很好。
首先,将它添加到您的UICollectionView子类:
override var intrinsicContentSize: CGSize {
get {
return self.contentSize
}
}
然后在重新加载数据后调用layoutIfNeeded():
reloadData()
layoutIfNeeded()
答案 3 :(得分:1)
我找到的最简单的方法是按原样覆盖sizeThatFits:
方法:
- (CGSize)sizeThatFits:(CGSize)size
{
if( self.superview )
[self.superview layoutIfNeeded]; // to force evaluate the real layout
return self.collectionViewLayout.collectionViewContentSize;
}
答案 4 :(得分:1)
与自定义UICollectionView类一起使用似乎效果很好。
class AutoSizedCollectionView: UICollectionView {
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
在界面生成器中设置您的自定义类:
这样,您还可以在界面生成器中将集合视图的固有大小设置为“占位符”,从而不必设置高度限制。
希望这对其他人有帮助。
答案 5 :(得分:0)
您可以试用我的自定义AGCollectionView
课程
UICollectionView
。class AGCollectionView: UICollectionView {
fileprivate var heightConstraint: NSLayoutConstraint!
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
self.associateConstraints()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.associateConstraints()
}
override open func layoutSubviews() {
super.layoutSubviews()
if self.heightConstraint != nil {
self.heightConstraint.constant = floor(self.contentSize.height)
}
else{
self.sizeToFit()
print("Set a heightConstraint set size to fit content")
}
}
func associateConstraints() {
// iterate through height constraints and identify
for constraint: NSLayoutConstraint in constraints {
if constraint.firstAttribute == .height {
if constraint.relation == .equal {
heightConstraint = constraint
}
}
}
}
}
答案 6 :(得分:0)
答案 7 :(得分:-3)
对我而言,我认为更简单
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//add following code line after adding cells, before Return
...........
.........
scrollView.contentSize = = collectionView.contentSize;
//now scrollView size is equal to collectionView size. No matter how small or big it is.
return cell;
}