首页 > 解决方案 > 何时调用 UICollectionViewDelegateFlowLayout 函数 sizeForItemAt

问题描述

我正在尝试根据方向以编程方式动态更改集合单元的大小。我曾经使用该sizeForItemAt功能来执行此操作,但我只发现当设备方向进入横向模式时才调用它。我应该使用这种方法还是可以使用不同的方法来实现?

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let sectionAttributes = SectionAttributesFactory.createSectionAttributes(for: indexPath.section)
        
        if UIDevice.current.orientation.isLandscape {
            print("Section: \(sectionAttributes.type) | lanscape: \(sectionAttributes.cellLayout.landscapeSize.width)")
        } else {
            print("Section: \(sectionAttributes.type) | portrait: \(sectionAttributes.cellLayout.portraitSize.width)")
        }
}

标签: iosswiftiphoneswift5

解决方案


collectionView(_:layout:sizeForItemAt:) 当 viewController 第一次加载和 collectionView 的布局无效时调用。您通常希望使布局无效viewWillTransition(to:with:)

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { context in
        self.collectionView.collectionViewLayout.invalidateLayout()
    })
}

然后您可以根据设备方向和视图大小更改单元格大小:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let cellsPerRow = UIDevice.current.orientation.isPortrait ? CGFloat(3.0) : CGFloat(4.0)
    let spacing = layout.minimumInteritemSpacing * (cellsPerRow - 1)
    let cellWidth = (view.frame.size.width - spacing) / cellsPerRow
    return .init(uniform: cellWidth)
}

推荐阅读