How to center align the cells of a UICollectionView in Swift3.0?

后端 未结 11 2102
不知归路
不知归路 2021-02-14 11:25

Description:

Answer for Objective-C and Swift2.0: How to center align the cells of a UICollectionView?

I usually would try to conver

相关标签:
11条回答
  • 2021-02-14 11:46
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
    
    let allCellWidth = KcellWidth * numberOfCell
    let cellSpacingWidth = CellSpacing * (numberOfCell - 1)
    
    let leftInset = (collectionViewWidth - CGFloat(allCellWidth + cellSpacingWidth)) / 2
    let rightInset = leftInset
    
    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
    }
    
    0 讨论(0)
  • 2021-02-14 11:49

    You need to conform to UICollectionViewDelegateFlowLayout protocol to find the collectionView(_:layout:insetForSectionAt:) method, it is defined there. the following implementation works fine in swift 4 for a horizontal collectionView

    extension YourViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
            let cellWidth = CGFloat(integerLiteral: YourCellsWidth)
            let count = self.YourCollectionViewDataSource.count
            let top = CGFloat(integerLiteral: 0)    // I don't need to set top and bottom spacing
            let cellsAccumulatedWidth = CGFloat(integerLiteral: count) * cellWidth
            let cellsSpacingAccumulatedWidth = CGFloat(integerLiteral: (count - 1) * 5)
            let left = (self.collectionView.frame.size.width - cellsAccumulatedWidth - cellsSpacingAccumulatedWidth) / 2
            let bottom = top
            let right = left
    
            return UIEdgeInsetsMake(top, left, bottom, right);
        }
    }
    
    0 讨论(0)
  • 2021-02-14 11:50

    While rottenoats answer is great, it has an extra spacing bug and doesn't use much of the available swift 3 syntax. I've fixed that and reduced the number of dependencies to local variables.

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    
        // Make sure that the number of items is worth the computing effort.
        guard let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout,
            let dataSourceCount = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: section),
            dataSourceCount > 0 else {
                return .zero
        }
    
    
        let cellCount = CGFloat(dataSourceCount)
        let itemSpacing = flowLayout.minimumInteritemSpacing
        let cellWidth = flowLayout.itemSize.width + itemSpacing
        var insets = flowLayout.sectionInset
    
    
        // Make sure to remove the last item spacing or it will
        // miscalculate the actual total width.
        let totalCellWidth = (cellWidth * cellCount) - itemSpacing
        let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right
    
    
        // If the number of cells that exist take up less room than the
        // collection view width, then center the content with the appropriate insets.
        // Otherwise return the default layout inset.
        guard totalCellWidth < contentWidth else {
            return insets
        }
    
    
        // Calculate the right amount of padding to center the cells.
        let padding = (contentWidth - totalCellWidth) / 2.0
        insets.left = padding
        insets.right = padding
        return insets
    }
    

    N.B.: This snippet only works for an horizontal scrolling but can easily be adjusted.

    0 讨论(0)
  • 2021-02-14 11:50

    Use this solution for horizontal scrolling with the center align.

    let totalCellWidth = Int(collectionView.frame.height * CGFloat(numberOfItems()))
    
            // if total width is greater than collection's width, then no need to align center
            if totalCellWidth > Int(collectionView.frame.width) {
                return UIEdgeInsets.zero
            }
    
            let totalSpacingWidth = cellSpacing * (numberOfItems() - 1)
            let leftInset = (collectionView.frame.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
            let rightInset = leftInset
            return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
    
    0 讨论(0)
  • 2021-02-14 11:52

    This code should center horizontally any type of collection view even with extra items in Swift 4.0:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
        let cellWidth: CGFloat = flowLayout.itemSize.width
        let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
        let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
        var collectionWidth = collectionView.frame.size.width
        if #available(iOS 11.0, *) {
            collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
        }
        let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
        if totalWidth <= collectionWidth {
            let edgeInset = (collectionWidth - totalWidth) / 2
            return UIEdgeInsetsMake(flowLayout.sectionInset.top, edgeInset, flowLayout.sectionInset.bottom, edgeInset)
        } else {
            return flowLayout.sectionInset
        }
    }
    

    Don't forget if you are not subclassing UICollectionViewController, make sure your class conforms to UICollectionViewDelegateFlowLayout protocol

    0 讨论(0)
提交回复
热议问题