我有一个UICollectionViewCell,里面有一个UICollectionViewUICollectionViewFlowLayout。我正在使单元格成为集合 View 的委托(delegate)和数据源。我符合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
  }
}

最佳答案

问题

  • 根据Apple documents for UICollectionViewFlowLayout's itemSize

  • 它清楚地表明itemSize仅在委托(delegate)未实现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)
    
  • 关于ios - 尽管实现了sizeForItemAt,UICollectionViewFlowLayout单元格的大小从未改变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47894895/

    10-12 06:07