UICollectionViewCell 和 UICollectionView 的高度相等

Posted

技术标签:

【中文标题】UICollectionViewCell 和 UICollectionView 的高度相等【英文标题】:Equal height of UICollectionViewCell's and UICollectionView 【发布时间】:2015-12-16 17:51:01 【问题描述】:

我应该如何设置 UICollectionView 中单元格的高度等于集合视图的高度?下面的代码不起作用,因为此时似乎不知道集合视图的高度,因为自动布局在这个阶段与属性混淆了。它会导致单元格高度高于实际的集合视图。

我会为解决这个问题的答案加 300 赏金!

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 

       return CGSize(width: 100, height: collectionView.frame.size.height)
    

2015-12-16 18:43:53.643 My-app[1055:434762] enter 的行为 这里的代码UICollectionViewFlowLayout没有定义,因为:2015-12-16 18:43:53.643 My-app[1055:434762] 项目高度必须小于 UICollectionView 的高度减去插入顶部和底部的部分 值,减去内容插入顶部和底部值。 2015-12-16 18:43:53.643 My-app[1055:434762] 请检查返回的值 代表。 2015-12-16 18:43:53.644 My-app[1055:434762] 相关 UICollectionViewFlowLayout 实例是,并且它附加到;层 = ;内容偏移:0, 0;内容大小:3087, 307> 集合视图布局:。 2015-12-16 18:43:53.644 My-app[1055:434762] 做一个符号断点 在 UICollectionViewFlowLayoutBreakForInvalidSizes 中捕获这个 调试器。

基于hannads 建议的解决方案。如果有更好的方法请告诉我

使用属性观察器创建属性。

var myCollectionViewHeight: CGFloat = 0.0 
    didSet 
        if myCollectionViewHeight != oldValue 
            myCollectionView.collectionViewLayout.invalidateLayout()
            myCollectionView.collectionViewLayout.prepareLayout()
        
    

重写此方法(多次调用)

override func viewDidLayoutSubviews() 
    myCollectionViewHeight = myCollectionView.bounds.size.height

然后我的委托中有这个:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize             
            return CGSize(width: 100, height: myCollectionViewHeight)
    

【问题讨论】:

【参考方案1】:

我会这样做。首先在视图控制器中添加一个全局变量,用于存储集合视图的高度。在viewDidLayoutSubviews方法中,将此变量设置为collectionView的高度,如果发生变化,调用方法使UICollectionView布局无效

collectionView.collectionViewLayout.invalidateLayout()

它将调用该方法来设置collectionView单元格的大小,并在该方法中将单元格的高度设置为保存collectionView高度的全局变量。

注意:目前在我的手机上,并没有测试此代码。我可能错过了什么。

【讨论】:

这离工作不远了。我会用完整的答案更新我的问题。 但是请注意,这将在开始时对集合视图进行一次布局,在您使布局无效之后再进行一次。不是最有效的解决方案,但我知道的一个。将等待您的更新。 @LuckyLuke 你提到viewDidLayoutSubviews 被多次调用。我认为每次设置myCollectionViewHeight 时都会调用didSet,即使它是相同的值。您能否在设置之前添加一个 if 语句来检查 myCollectionViewHeight 是否不等于 myCollectionView.bounds.size.height?这可能会有所帮助。 是的,我能做到。每次使用当前设置的 viewDidLayoutSubviews 都会调用设置属性观察者。我会改变你的建议。它不会改变 viewDidLayoutSubviews 被多次调用的事实,但我想这是正确的,因为自动布局正在调整或类似的东西。 @LuckyLuke 你说离工作不远了。它仍然给您带来问题吗?【参考方案2】:

您尝试将此代码设置为您的viewDidLoad

self.automaticallyAdjustsScrollViewInsets = false

希望对您有所帮助!

【讨论】:

在情节提要中设置此属性也有助于偏移。否则,当您将任何 UICollectionView 放入 UINavigationController 时,它都会被下推。取消选中“调整滚动视图插图” 'automaticallyAdjustsScrollViewInsets' was deprecated in ios 11.0: Use UIScrollView's contentInsetAdjustmentBehavior instead【参考方案3】:

我已经为这个问题苦苦挣扎了一个多星期,终于找到了适合我的具体案例的答案。我的问题是 1) 在 UICollectionViewCell 的图像中加载远程图像的结果,以及 2) 估计的单元格大小大于我在集合视图布局的 sizeForItemAt 上手动设置的大小。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    return CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height)

我能够通过将情节提要上的单元格大小减小到低于单元格大小的数量来解决,并且我还将“估计大小”设置为“无”(这最后一部分可能就足够了)

【讨论】:

祝福你。你的回答就是为什么我仍然可以在这个月完成我的最后期限。【参考方案4】:

就我而言,我必须将collectionViewLayout.estimatedItemSize 设置为一个显式值(其高度UICollectionViewFlowLayout.automaticSize。

UICollectionViewFlowLayout.automaticSize 的默认单元格大小为 50pt x 50pt,高于我的收藏视图。在这种情况下,UIKit 拒绝做任何布局工作,尽管自调整大小计算后的实际单元格大小会更小。

// horizontally scrollable collection view

private var viewHeight: CGFloat?

override func viewWillLayoutSubviews() 
    super.viewWillLayoutSubviews()
    
    if viewHeight != view.bounds.height 
        viewHeight = view.bounds.height
        layout.estimatedItemSize = CGSize(width: 50, height: viewHeight!)
        layout.invalidateLayout()
    

【讨论】:

【参考方案5】:

我遇到了这个问题,因为我将UICollectionView 固定在UITableViewCell 的底部,而没有给collectionView 指定高度。

在发出几个网络请求然后在UIViewController 中调用[self.tableView reloadData] 后,我在日志中收到了相同的错误消息。

我设法通过打破底部约束并给UICollectionView 一个固定高度来解决它。

【讨论】:

【参考方案6】:

我也遇到了这个问题,我可以通过减去相关的sectionInsets 来解决它。减去 .size.height 属性中未考虑的插入后,它就会接受高度。

sizeForItemAtIndexPath 内,您需要减去部分插图尺寸...

  let sectionInset = self.collectionView?.collectionViewLayout.sectionInset
  let heightToSubtract = sectionInset!.top + sectionInset!.bottom

  return CGSize(width: 100.0, height: (self.collectionView?.bounds.height)! - heightToSubtract)

注意:我在这里强制解包选项,但为了安全起见,您可能需要检查它们

【讨论】:

但问题是我已使用委托方法将 insets 设置为 0。那么这不应该是必要的。 @LuckyLuke 我假设您也将 contentInset 设置为 0?你已经打印出这些值并且可以确认一切都是0?那我不知道,因为有些东西告诉你的高度大于设置的 collectionView.bounds.height 并且如果不看项目就很难分辨【参考方案7】:

在我的例子中,我将collectionview添加到tableviewcell,collectionview item height等于tableviewcell height。当更改 tableviewcellheiht 时,我收到此警告。 要解决这个问题,试试这段代码

  if (@available(iOS 11.0, *)) 
        _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
     else 
    

【讨论】:

【参考方案8】:

这个问题可以通过在 viewdidload 中设置 collectionViewLayout itemSize 属性来轻松解决:

collectionViewLayout.itemSize = .init(width: 80, height: 80)

【讨论】:

【参考方案9】:

我用这个解决方案解决了这个问题:

    单元格大小等于集合视图大小

2. 故事板“Inset from:”从 Safe Area 更改为 Content Inset

    将“内容插入”更改为从不

【讨论】:

以上是关于UICollectionViewCell 和 UICollectionView 的高度相等的主要内容,如果未能解决你的问题,请参考以下文章

具有动态高度的 UICollectionViewCell 使用 NSURL 进行图像下载

滚动时大型 UICollectionViewCell 停止显示

基于UILabel的UICollectionViewCell AutoLayout动态高度

如何确定何时显示 UICollectionViewCell?

XCTest 与自定义 UICollectionViewCell

将 UIViewController 添加到 UICollectionViewCell