简体   繁体   中英

When is UICollectionViewDelegateFlowLayout function sizeForItemAt called

I am trying to programmatically change the size of collection cells dynamically based on orientation. I am using to use the sizeForItemAt function to do so, but I am only finding it being called when the device orientation goes to landscape mode. Should I be using this method or could this be achieved using a different approach?

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)")
        }
}

U can just reload your collectionView on screen rotate using:

override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    collectionView.reloadData()
}

This way size for item will be called again. Also there are more modes than.landscape and.portrait, for more info: https://developer.apple.com/documentation/uikit/uideviceorientation

collectionView(_:layout:sizeForItemAt:) is called when the viewController first loads and when the collectionView's layout is invalidated. You typically want to invalidate the layout in 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()
    })
}

Then you can make changes to cell sizes based on the device orientation and view size:

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)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM