UICollectionView 缝隙修复

orgq5556 9年前
   <p>在开发中有时可能你的 UICollectionView 需要一行 无缝 放置4个cell。在5s上是完美的,6或者6p上应该是这样的:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a487026fc48e22e6f7e18dd6e5fa4723.png"></p>    <p>你的第一反应肯定是去检查 layout 的 minimumInteritemSpacing 。</p>    <p>然而</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/560333596011379d55d3b6241e07b06a.png"></p>    <p>就是设置为0的,怎么会这样?</p>    <p>也有可能你需要一行放置3个cell,间隔为1px。可能会是这样的:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/faf0076bab5dfdbae20c4dd266fa7066.png"></p>    <p>你的第一反应肯定还是去检查 layout 的 minimumInteritemSpacing 。</p>    <p>然而</p>    <p><img src="https://simg.open-open.com/show/7bc4b5d4e8afef4baa3b4287a95d8a2a.png"></p>    <h2><strong>原因</strong></h2>    <p>罪魁祸首就是像素,手机屏幕最小的单位是像素也就是1px,当小于1px时,像素是不可再分的,就造成了上面的现象。(1px = 0.5pt)</p>    <p>在上面设置 itemSize 宽度时就是因为像素不够分了375 / 4 = 93.75,根据上面的关系可知,小数点后只有1位且最小为5。</p>    <p>第二种情况同理 374 / 3 = 124.66666666666667</p>    <p>我在网上查了一下,主要的解决办法主要是重写 UICollectionViewFlowLayout ,还有设置 sectionInset ,似乎都有点麻烦,也没能最终解决问题。这篇 文章 的思路才是我们想要的,不过只处理了无缝情况。</p>    <h2><strong>debug代码</strong></h2>    <p>先贴出代码</p>    <p>Swift2.3</p>    <pre>  <code class="language-objectivec">/// 修正collection布局有缝隙      func fixSlit(inout rect: CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {          let totalSpace = (colCount - 1) * space          let itemWidth = (rect.width - totalSpace) / colCount          var realItemWidth = floor(itemWidth) + 0.5          if realItemWidth < itemWidth {              realItemWidth += 0.5          }          let realWdth = colCount * realItemWidth + totalSpace          let pointX = (realWdth - rect.width) / 2          rect.origin.x = -pointX          rect.size.width = realWdth          return (rect.width - totalSpace) / colCount      }</code></pre>    <p>Swift3</p>    <pre>  <code class="language-objectivec">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          var realItemWidth = floor(itemWidth) + 0.5          if realItemWidth < itemWidth {              realItemWidth += 0.5          }          let realWdth = colCount * realItemWidth + totalSpace          let pointX = (realWdth - rect.width) / 2          rect.origin.x = -pointX          rect.size.width = realWdth          return (rect.width - totalSpace) / colCount      }  }</code></pre>    <h2><strong>修复之后</strong></h2>    <p>无缝</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/88bac0ffa3aa650583f51772c629a3d9.png"></p>    <p>1px缝隙\</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/836b215d69a9a0dc66c68958dc119283.png"></p>    <h2><strong>思路</strong></h2>    <p>根据上面bug出现的原因,我们知道只要 itemSize 的 width 的小数点后只有1位且最小为5也就是满足 1px=0.5pt 这个等式。</p>    <pre>  <code class="language-objectivec">func fixSlit(inout rect: CGRect, colCount: CGFloat, space: CGFloat = 0) -> CGFloat {          let totalSpace = (colCount - 1) * space // 总共留出的距离          let itemWidth = (rect.width - totalSpace) / colCount  // 按照真实屏幕算出的cell宽度          var realItemWidth = floor(itemWidth) + 0.5 // 取整加0.5(1px=0.5pt)          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真实宽度      }</code></pre>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/4db0be2f4803</p>    <p> </p>