【问题标题】:UICollectionViewFlowLayout cell size never changes despite sizeForItemAt implemented尽管实现了 sizeForItemAt,但 UICollectionViewFlowLayout 单元格大小永远不会改变
【发布时间】:2017-12-19 20:43:25
【问题描述】:

我有一个UICollectionViewCell,里面有一个UICollectionView,里面有UICollectionViewFlowLayout。我正在使单元格成为集合视图的委托和数据源。我符合UICollectionViewDelegateFlowLayout 并实现collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize(并返回正确的大小)。

但是,当我调用 layout.itemSize.height 时,我得到默认高度 50。

class MyCell: UICollectionViewCell {
  fileprivate lazy var collectionView: UICollectionView = {
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.register(SomeOtherCell.self, forCellWithReuseIdentifier: SomeOtherCell.reuseIdentifier)
    collectionView.showsHorizontalScrollIndicator = false
    collectionView.showsVerticalScrollIndicator = false
    return collectionView
  }()

  fileprivate lazy var layout: UICollectionViewFlowLayout? = {
    let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    layout?.scrollDirection = .horizontal
    layout?.sectionInset = UIEdgeInsets.zero
    return layout
  }()

  override func sizeThatFits(_ size: CGSize) -> CGSize {
  collectionView.frame = CGRect(x: layoutMargins.left, y: origin.y, width: width, height: layout.itemSize.height)
  // layout.itemSize.height is always 50
  }
}
extension MyCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    guard tags.count != 0 else {
        return .zero
    }

    let tag = Tag(text: tags[indexPath.item], index: indexPath.item)
    placeholderCell.configure(with: tag)
    let size = placeholderCell.getFrame(at: .zero, fitting: placeholderCell.width, alignedBy: semanticContentAttribute, apply: false).size
    collectionViewWidth += size.width
  // this size is always correct, that's what I want when I call  layout.itemSize.height 
    return size
  }
}

【问题讨论】:

    标签: ios swift uicollectionview uicollectionviewlayout


    【解决方案1】:

    问题

    • 根据Apple documents for UICollectionViewFlowLayout's itemSize

      如果delegate没有实现collectionView(_:layout:sizeForItemAt:)方法,流布局使用这个属性中的值来设置每个单元格的大小。这会导致所有单元格的大小都相同。

      默认大小值为 (50.0, 50.0)。

    • 它明确表示itemSize 仅在委托未实现 collectionView(_:layout:sizeForItemAt:) 方法并且没有提及itemSize 将从collectionView(_:layout:sizeForItemAt:) 返回值时使用。 它们是 2 个不同的值。这就是为什么 itemSize 不会改变,尽管 sizeForItemAt 已实现

      因此,如果layout.itemSize.height 在您使用时具有默认值 (50),则它是有意义的。

    您的问题有什么解决方案?

    • 如果collectionView 上的所有单元格大小相同,我建议为itemSize 设置一个值,并且不要实现collectionView(_:layout:sizeForItemAt:) 方法(删除UICollectionViewDelegateFlowLayout 的扩展名)。

      class MyCell: UICollectionViewCell {
        fileprivate lazy var collectionView: UICollectionView = {
          let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
          // collectionView.delegate = self
          collectionView.dataSource = self
          collectionView.register(SomeOtherCell.self, forCellWithReuseIdentifier: SomeOtherCell.reuseIdentifier)
          collectionView.showsHorizontalScrollIndicator = false
          collectionView.showsVerticalScrollIndicator = false
          return collectionView
        }()
      
        fileprivate lazy var layout: UICollectionViewFlowLayout? = {
          let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
          layout?.scrollDirection = .horizontal
          layout?.sectionInset = UIEdgeInsets.zero
          // Calculate and change |itemSize| here
          layout?.itemSize = YOUR_CELL_SIZE_AFTER_CALCULATED
          return layout
        }()
      
        override func sizeThatFits(_ size: CGSize) -> CGSize {
          collectionView.frame = CGRect(x: layoutMargins.left, y: origin.y, width: width, height: layout.itemSize.height)
          // layout.itemSize.height is |YOUR_CELL_SIZE_AFTER_CALCULATED.height|
        }
      }
      
    • 如果collectionView 的每个单元格大小不同,则需要使用UICollectionView's layoutAttributesForItem(at:) method。在 IndexPath 处获取 UICollectionViewLayoutAttributes 并使用 layoutAttributes.size 计算

      layoutAttributes.size 是从collectionView(_:layout:sizeForItemAt:) 返回的值

      let indexPath = // IndexPath you need to use to calculate
      let layoutAttributes : UICollectionViewLayoutAttributes? = collectionView.layoutAttributesForItem(at: indexPath)
      //  Use this value to calculate |collectionView| frame
      print(layoutAttributes?.size)
      

    【讨论】:

      【解决方案2】:

      我认为您的注册问题...删除它并在情节提要中设置单元格。只是一个疯狂的猜测......

      您有 2 个单元格,其中一个已为 collectionView 注册?

      如果你在storyboard中设置单元格,注册也可能会导致问题

        collectionView.register(SomeOtherCell.self, forCellWithReuseIdentifier: SomeOtherCell.reuseIdentifier)
      

      【讨论】:

        猜你喜欢
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多