iOS 九空格&UICollectionView布局中的
在开发中有时可能你的
UICollectionView
需要一行无缝放置4个cell。在5s上是完美的,6或者6p上应该是这样的:
![](https://img.haomeiwen.com/i2567136/aac0b26d81631638.png)
你的第一反应肯定是去检查layout的minimumInteritemSpacing
。然而
![](https://img.haomeiwen.com/i2567136/9c988a8b71f31111.png)
就是设置为0的,怎么会这样?
![](https://img.haomeiwen.com/i2567136/c2135853bc5211de.png)
你的第一反应肯定还是去检查layout的minimumInteritemSpacing
。然而
![](https://img.haomeiwen.com/i2567136/b56977bb43b3aeeb.png)
原因
罪魁祸首就是像素,手机屏幕最小的单位是像素也就是1px,当小于1px时,像素是不可再分的,就造成了上面的现象。(1px = 0.5pt)
iPhone6的屏幕像素(point,也叫逻辑像素)是375667,物理像素为7501334,等分4份的话每一个item的宽度是375/4=93.75,这里是没有问题的,问题是屏幕能分的最小物理像素是1,而iPhone6的[[UIScreen mainScrenn] scale]是2.0,也就是说1个屏幕像素(逻辑像素)对应有2个物理像素,即0.5个屏幕像素对应1个物理像素,而iPhone6四等分的宽度是93.75,根据前面的分析有0.25是不可再分的,这就是造成缝隙的原因。
同理iPhone6 Plus的[[UIScreen mainScrenn] scale]是3.0,也就是说1个屏幕像素(逻辑像素)对应有3个物理像素,即0.333333个屏幕像素对应1个物理像素,四等分之后是414/4=103.5,有0.16是不可再分的,也会有缝隙
在上面设置itemSize
宽度时就是因为像素不够分了375 / 4 = 93.75,根据上面的关系可知,小数点后只有1位且最小为5。
第二种情况同理374 / 3 = 124.66666666666667
我在网上查了一下,主要的解决办法主要是重写UICollectionViewFlowLayout
,还有设置sectionInset
,似乎都有点麻烦,也没能最终解决问题。这篇文章的思路才是我们想要的,不过只处理了无缝情况。
extension UICollectionViewFlowLayout {
/// 修正collection布局有缝隙
func fixSlit(rect: inout CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {
let totalSpace = (colCount - 1) * space
let itemWidth = (rect.width - totalSpace) / colCount
let fixValue = 1 / UIScreen.main.scale
var realItemWidth = floor(itemWidth) + fixValue
if realItemWidth < itemWidth {
realItemWidth += fixValue
}
let realWidth = colCount * realItemWidth + totalSpace
let pointX = (realWidth - rect.width) / 2
rect.origin.x = -pointX
rect.size.width = realWidth
return (rect.width - totalSpace) / colCount
}
}
![](https://img.haomeiwen.com/i2567136/2a0e30f4a6da9534.png)
思路
根据上面bug出现的原因,我们知道只要itemSize的width的小数点后只有1位且最小为5也就是满足
1px=0.5pt
这个等式。
func fixSlit(inout rect: CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {
let totalSpace = (colCount - 1) * space // 总共留出的距离
let itemWidth = (rect.width - totalSpace) / colCount // 按照真实屏幕算出的cell宽度
let fixValue = 1 / UIScreen.mainScreen().scale (1px=0.5pt,6p为3px=1pt)
var realItemWidth = floor(itemWidth) + fixValue // 取整加fixValue
if realItemWidth < itemWidth { // 有可能原cell宽度小数点后一位大于0.5
realItemWidth += 0.5
}
let realWidth = colCount * realItemWidth + totalSpace // 算出屏幕等分后满足`1px=0.5pt`实际的宽度
let pointX = (realWidth - rect.width) / 2 // 偏移距离
rect.origin.x = -pointX // 向左偏移
rect.size.width = realWidth
return (rect.width - totalSpace) / colCount // 每个cell真实宽度
}
参考资料
https://www.jianshu.com/p/01cadd95604d
https://www.jianshu.com/p/4db0be2f4803
https://github.com/huicongfu/FixUICollectionViewSlit
http://www.cnblogs.com/smileEvday/p/iOS_PixelVsPoint.html
https://www.zhihu.com/question/27261444