美文网首页
UICollectionViewFlowLayout计算item

UICollectionViewFlowLayout计算item

作者: 字节码 | 来源:发表于2019-12-21 15:35 被阅读0次

    使用UICollectionViewFlowLayout时, cell的宽度计算误差导致collectionView cell的间距不对, 或者明明想一行展示3个, 实际效果却一张展示了2个,
    UICollectionViewFlowLayout提供了minimumInteritemSpacing和minimumLineSpacing, 用于设置item之间的间距和行之间的间距.
    在计算item的宽高时, 明确了一行展示item的个数, 所以经常使用这两个属性计算宽高,
    而有时比较奇怪的是, 计算好的宽度, 最终一行少显示了一个, 或者item之间的间距莫名的变大.

    错误计算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

    正确计算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)
    

    原因: 这是由于, 计算宽度时, 得到的是精确的float类型的宽宽, 而item的宽度必须是一个向下取整的整数, 否则item的宽度大了, 自然会导致一行展示不下的情况.
    在计算item宽度时, 使用floor函数向下取整, 解决问题

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

    相关文章

      网友评论

          本文标题:UICollectionViewFlowLayout计算item

          本文链接:https://www.haomeiwen.com/subject/dfegnctx.html