在開(kāi)發(fā)中有時(shí)可能你的
UICollectionView需要一行無(wú)縫放置4個(gè)cell。在5s上是完美的,6或者6p上應(yīng)該是這樣的:

你的第一反應(yīng)肯定是去檢查layout的minimumInteritemSpacing。
然而

就是設(shè)置為0的,怎么會(huì)這樣?
也有可能你需要一行放置3個(gè)cell,間隔為1px。可能會(huì)是這樣的:

你的第一反應(yīng)肯定還是去檢查layout的minimumInteritemSpacing。
然而

原因
罪魁禍?zhǔn)拙褪窍袼?,手機(jī)屏幕最小的單位是像素也就是1px,當(dāng)小于1px時(shí),像素是不可再分的,就造成了上面的現(xiàn)象。(1px = 0.5pt)
在上面設(shè)置itemSize寬度時(shí)就是因?yàn)橄袼夭粔蚍至?75 / 4 = 93.75,根據(jù)上面的關(guān)系可知,小數(shù)點(diǎn)后只有1位且最小為5。
第二種情況同理 374 / 3 = 124.66666666666667
我在網(wǎng)上查了一下,主要的解決辦法主要是重寫(xiě)UICollectionViewFlowLayout,還有設(shè)置sectionInset,似乎都有點(diǎn)麻煩,也沒(méi)能最終解決問(wèn)題。這篇文章的思路才是我們想要的,不過(guò)只處理了無(wú)縫情況。
debug代碼
先貼出代碼
Swift2.3
/// 修正collection布局有縫隙
func fixSlit(inout rect: CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {
let totalSpace = (colCount - 1) * space
let itemWidth = (rect.width - totalSpace) / colCount
let fixValue = 1 / UIScreen.mainScreen().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
}
Swift3
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
}
}
修復(fù)之后
無(wú)縫

1px縫隙\

思路
根據(jù)上面bug出現(xiàn)的原因,我們知道只要itemSize的width的小數(shù)點(diǎn)后只有1位且最小為5也就是滿足1px=0.5pt這個(gè)等式。
func fixSlit(inout rect: CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {
let totalSpace = (colCount - 1) * space // 總共留出的距離
let itemWidth = (rect.width - totalSpace) / colCount // 按照真實(shí)屏幕算出的cell寬度
let fixValue = 1 / UIScreen.mainScreen().scale (1px=0.5pt,6p為3px=1pt)
var realItemWidth = floor(itemWidth) + fixValue // 取整加fixValue
if realItemWidth < itemWidth { // 有可能原cell寬度小數(shù)點(diǎn)后一位大于0.5
realItemWidth += 0.5
}
let realWidth = colCount * realItemWidth + totalSpace // 算出屏幕等分后滿足`1px=0.5pt`實(shí)際的寬度
let pointX = (realWidth - rect.width) / 2 // 偏移距離
rect.origin.x = -pointX // 向左偏移
rect.size.width = realWidth
return (rect.width - totalSpace) / colCount // 每個(gè)cell真實(shí)寬度
}