使用UICollectionViewFlowLayout時, cell的寬度計算誤差導致collectionView cell的間距不對, 或者明明想一行展示3個, 實際效果卻一張展示了2個,
UICollectionViewFlowLayout提供了minimumInteritemSpacing和minimumLineSpacing, 用于設置item之間的間距和行之間的間距.
在計算item的寬高時, 明確了一行展示item的個數(shù), 所以經(jīng)常使用這兩個屬性計算寬高,
而有時比較奇怪的是, 計算好的寬度, 最終一行少顯示了一個, 或者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的寬度必須是一個向下取整的整數(shù), 否則item的寬度大了, 自然會導致一行展示不下的情況.
在計算item寬度時, 使用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)
}
}