iOS Collection View单元格未按正确列数渲染问题求助
搞定UICollectionView 3列布局的排列问题
嘿,我看你这UICollectionView的3列布局排列有点不对劲儿——4个item时第4个跑第二行最右边,2个item时中间还空着,这大概率是FlowLayout默认居中对齐搞的鬼,核心原因是你算的item尺寸加起来没填满屏幕宽度,系统就自动把item组居中了。
为啥会这样?
从你给的代码来看,在3列布局场景下:
- 你先算出每个item的基础宽度是屏幕宽度的1/3(因为间距设为0)
- 但最后返回的item宽度却减了1pt,这就导致3个item加起来总宽度比屏幕少了3pt
- FlowLayout一看有空隙,就自动把item组居中,结果2个item时就变成
|1| |2|,4个item时第二行的单个item就跑到最右边去了
怎么改?
第一步:修正Item尺寸计算
得保证item总宽度加间距刚好填满屏幕,别再随便减1了!调整后的代码如下:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.orientation.isLandscape { let cellsAcross: CGFloat = 3 let spaceBetweenCells: CGFloat = 0 // 要间距的话这里改数值,比如1 // 公式:(屏幕宽度 - (列数-1)*列间距) / 列数,保证总宽度刚好填满 let itemWidth = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross return CGSize(width: itemWidth, height: 110) } else { let cellsAcross: CGFloat = 2 let spaceBetweenCells: CGFloat = 0 let itemWidth = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross return CGSize(width: itemWidth, height: 110) } }
第二步:给FlowLayout做个正确配置
还要确保你的布局没有额外的内边距,间距和计算时保持一致:
// 初始化collectionView的时候设置layout let flowLayout = UICollectionViewFlowLayout() flowLayout.minimumInteritemSpacing = 0 // 和上面sizeForItem里的spaceBetweenCells数值一致 flowLayout.minimumLineSpacing = 10 // 行间距按需调,比如10pt flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // 不要留额外的边距 collectionView.collectionViewLayout = flowLayout
第三步:屏幕旋转时刷新布局
因为你根据横竖屏切换列数,所以旋转屏幕时要让布局重新计算:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) // 刷新布局,让新的列数生效 collectionView.collectionViewLayout.invalidateLayout() }
改完后的效果
- 4个item时,排列就变成你要的样子:
|1|2|3|
|4| | | - 2个item时,也会正常左对齐:
|1|2| |
完美解决问题啦!
内容的提问来源于stack exchange,提问作者iCodes
相关产品推荐
相关产品推荐

