UICollectionViewFlowLayout計(jì)算item寬度時(shí), 莫名導(dǎo)致item間距不對或者每行展示的數(shù)據(jù)不符合預(yù)期

使用UICollectionViewFlowLayout時(shí), cell的寬度計(jì)算誤差導(dǎo)致collectionView cell的間距不對, 或者明明想一行展示3個(gè), 實(shí)際效果卻一張展示了2個(gè),
UICollectionViewFlowLayout提供了minimumInteritemSpacing和minimumLineSpacing, 用于設(shè)置item之間的間距和行之間的間距.
在計(jì)算item的寬高時(shí), 明確了一行展示item的個(gè)數(shù), 所以經(jīng)常使用這兩個(gè)屬性計(jì)算寬高,
而有時(shí)比較奇怪的是, 計(jì)算好的寬度, 最終一行少顯示了一個(gè), 或者item之間的間距莫名的變大.

錯(cuò)誤計(jì)算item寬度的代碼:

        let filterSection = self.viewModel!.templates[indexPath.section]
        let item = filterSection.displayItems[indexPath.row]
        let contentWidth = collectionView.frame.size.width - CGFloat(filterSection.numberOfOneLine + 1) * GoodsFilterViewModel.kItemSpacing
        let width = contentWidth / CGFloat(filterSection.numberOfOneLine)
        return CGSize(width: width, height: item.rowHeight)

問題圖片:


0EB6C2DF6CED946316EC7BC1DB0AA61F.png

解決后的截圖:


482131BE0B639874234620B4F9065968.png

正確計(jì)算item寬度的代碼(使用floor向下取整):

let filterSection = self.viewModel!.templates[indexPath.section]
        let item = filterSection.displayItems[indexPath.row]
        let contentWidth = collectionView.frame.size.width - CGFloat(filterSection.numberOfOneLine + 1) * GoodsFilterViewModel.kItemSpacing
        let width = CGFloat(floor(contentWidth / CGFloat(filterSection.numberOfOneLine)))
        return CGSize(width: width, height: item.rowHeight)

原因: 這是由于, 計(jì)算寬度時(shí), 得到的是精確的float類型的寬寬, 而item的寬度必須是一個(gè)向下取整的整數(shù), 否則item的寬度大了, 自然會導(dǎo)致一行展示不下的情況.
在計(jì)算item寬度時(shí), 使用floor函數(shù)向下取整, 解決問題

demo部分代碼:

class GoodsFilterViewModel: NSObject {
    
    lazy var templates = [GoodsFilterViewSection]()
    static let kItemSpacing: CGFloat = 8.0
    static let kItemHeight: CGFloat = 45.0
}

class GoodsFilterViewController: UIViewController {
   
    private lazy var collectionView: UICollectionView = {
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.scrollDirection = .vertical
        flowLayout.minimumInteritemSpacing = GoodsFilterViewModel.kItemSpacing
        flowLayout.minimumLineSpacing = GoodsFilterViewModel.kItemSpacing
        flowLayout.sectionHeadersPinToVisibleBounds = true
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.isScrollEnabled = true
        collectionView.backgroundColor = UIColor.white
        collectionView.keyboardDismissMode = .onDrag
        collectionView.alwaysBounceVertical = true
        collectionView.showsVerticalScrollIndicator = false
        return collectionView
    }()
    
}
extension GoodsFilterViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let filterSection = self.viewModel!.templates[indexPath.section]
        let item = filterSection.displayItems[indexPath.row]
        let contentWidth = collectionView.frame.size.width - CGFloat(filterSection.numberOfOneLine + 1) * GoodsFilterViewModel.kItemSpacing
        let width = CGFloat(floor(contentWidth / CGFloat(filterSection.numberOfOneLine)))
        return CGSize(width: width, height: item.rowHeight)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let padding = GoodsFilterViewModel.kItemSpacing
        return UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容