tomiOS自学之路Swift开发指导

UICollectionView 缝隙修复

2016-11-28  本文已影响1451人  xiAo__Ju

在开发中有时可能你的UICollectionView需要一行无缝放置4个cell。在5s上是完美的,6或者6p上应该是这样的:

Simulator Screen Shot 2016年11月28日 下午4.46.11.png

你的第一反应肯定是去检查layoutminimumInteritemSpacing
然而

屏幕快照 2016-11-28 下午4.46.16.png

就是设置为0的,怎么会这样?

也有可能你需要一行放置3个cell,间隔为1px。可能会是这样的:

Simulator Screen Shot 2016年11月28日 下午4.56.06.png

你的第一反应肯定还是去检查layoutminimumInteritemSpacing
然而

屏幕快照 2016-11-28 下午4.56.15.png

原因

罪魁祸首就是像素,手机屏幕最小的单位是像素也就是1px,当小于1px时,像素是不可再分的,就造成了上面的现象。(1px = 0.5pt)
在上面设置itemSize宽度时就是因为像素不够分了375 / 4 = 93.75,根据上面的关系可知,小数点后只有1位且最小为5。
第二种情况同理 374 / 3 = 124.66666666666667

我在网上查了一下,主要的解决办法主要是重写UICollectionViewFlowLayout,还有设置sectionInset,似乎都有点麻烦,也没能最终解决问题。这篇文章的思路才是我们想要的,不过只处理了无缝情况。

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
    }
}

修复之后

无缝

Simulator Screen Shot 2016年11月28日 下午5.28.57.png

1px缝隙\

Simulator Screen Shot 2016年11月28日 下午5.29.01.png

思路

根据上面bug出现的原因,我们知道只要itemSizewidth的小数点后只有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真实宽度
    }

Demo

上一篇 下一篇

猜你喜欢

热点阅读