在開發(fā)中有時可能你的
UICollectionView
需要一行無縫放置4個cell紫谷。在5s上是完美的齐饮,6或者6p上應(yīng)該是這樣的:
你的第一反應(yīng)肯定是去檢查layout的minimumInteritemSpacing
捐寥。然而
就是設(shè)置為0的,怎么會這樣笤昨?
你的第一反應(yīng)肯定還是去檢查layout的minimumInteritemSpacing
。然而
原因
罪魁禍?zhǔn)拙褪窍袼匚湛遥謾C屏幕最小的單位是像素也就是1px瞒窒,當(dāng)小于1px時,像素是不可再分的乡洼,就造成了上面的現(xiàn)象崇裁。(1px = 0.5pt)
iPhone6的屏幕像素(point,也叫邏輯像素)是375667,物理像素為7501334,等分4份的話每一個item的寬度是375/4=93.75,這里是沒有問題的,問題是屏幕能分的最小物理像素是1,而iPhone6的[[UIScreen mainScrenn] scale]是2.0,也就是說1個屏幕像素(邏輯像素)對應(yīng)有2個物理像素,即0.5個屏幕像素對應(yīng)1個物理像素,而iPhone6四等分的寬度是93.75,根據(jù)前面的分析有0.25是不可再分的,這就是造成縫隙的原因。
同理iPhone6 Plus的[[UIScreen mainScrenn] scale]是3.0,也就是說1個屏幕像素(邏輯像素)對應(yīng)有3個物理像素,即0.333333個屏幕像素對應(yīng)1個物理像素,四等分之后是414/4=103.5,有0.16是不可再分的,也會有縫隙
在上面設(shè)置itemSize
寬度時就是因為像素不夠分了375 / 4 = 93.75,根據(jù)上面的關(guān)系可知束昵,小數(shù)點后只有1位且最小為5拔稳。
第二種情況同理374 / 3 = 124.66666666666667
我在網(wǎng)上查了一下,主要的解決辦法主要是重寫UICollectionViewFlowLayout
,還有設(shè)置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
}
}
思路
根據(jù)上面bug出現(xiàn)的原因轻绞,我們知道只要itemSize的width的小數(shù)點后只有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寬度小數(shù)點后一位大于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真實寬度
}
參考資料
http://www.reibang.com/p/01cadd95604d
http://www.reibang.com/p/4db0be2f4803
https://github.com/huicongfu/FixUICollectionViewSlit
http://www.cnblogs.com/smileEvday/p/iOS_PixelVsPoint.html
https://www.zhihu.com/question/27261444