UICollectionView 缝隙修复

作者: xiAo__Ju | 来源:发表于2016-11-28 18:51 被阅读1451次

    在开发中有时可能你的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

    相关文章

      网友评论

      • 迷恋代码:楼主,为什么我xib弄的cell按照你的方法中间还是有间隙
        迷恋代码:@xiAo__Ju 这个纯代码布局有关系吗
        迷恋代码:@xiAo__Ju 恩
        xiAo__Ju:你用的autolayout布局吧
      • 无法触碰:请问,OC该怎么处理?cell和ICollectionView等大, 开启分页效果后,划玩了item直接从0变成2了,
        xiAo__Ju:你是做轮播吗
      • 小番茄阳阳:375 / 4 用这个方法就等于94 94 * 4 =376 ,就不够放四个了,只能放三个 怎么解决
      • sclcoder:如果collectionView有多个不同列数的section,这个调整会有问题吧
      • 温特儿:是否可以这样理解:
        1,collectionView偏移-pointX,宽度增加了2*pointX;
        2,cell的宽度其实就是realItemWidth。
        xiAo__Ju:@winterSeven 对的
      • cd7bb10cf1dd:很棒,最近也遇到这个问题,非常感谢!!
      • 四菜一躺:不错,刚好遇到这个问题,感谢
        xiAo__Ju:@四菜一躺 哥们抱歉,之前写的版本在6p上有问题,已更新!
        xiAo__Ju:@四菜一躺 能帮到你就好!

      本文标题:UICollectionView 缝隙修复

      本文链接:https://www.haomeiwen.com/subject/ubpopttx.html