luck
Keep Happy Every Day
2016-06-16T14:36:45.000Z
http://meigesir.github.io/
meigesir
emomeild@gmail.com
Hexo
collectionView自定义layout
http://meigesir.github.io/2016/06/06/collectionView_custom_layout/
2016-06-06T06:13:54.000Z
2016-06-16T14:36:45.000Z
<p>自定义layout前,先来看看UICollectionView。</p>
<h2 id="什么是UICollectionView"><a href="#什么是UICollectionView" class="headerlink" title="什么是UICollectionView"></a>什么是UICollectionView</h2><p>UICollectionView是一种新的数据展示方式,简单来说可以把他理解成多列的UITableView(请一定注意这是UICollectionView的最最简单的形式)。</p>
<a id="more"></a>
<h2 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h2><p>首先回顾一下Collection View的构成,我们能看到的有三个部分:</p>
<ul>
<li>Cells 用于展示内容的主体,对于不同的cell可以指定不同尺寸和不同的内容</li>
<li>Supplementary Views 追加视图 (类似UITableView Header或者Footer,但是只发挥了10%的功力)</li>
<li>Decoration Views 装饰视图 (用作背景展示)</li>
</ul>
<h3 id="关于重用"><a href="#关于重用" class="headerlink" title="关于重用"></a>关于重用</h3><p>为了得到高效的View,对于cell的重用是必须的,避免了不断生成和销毁对象的操作,这与在UITableView中的情况是一致的。但值得注意的时,在UICollectionView中,不仅cell可以重用,Supplementary View和Decoration View也是可以并且应当被重用的。</p>
<h3 id="关于Cell"><a href="#关于Cell" class="headerlink" title="关于Cell"></a>关于Cell</h3><p>SDK提供给我们的默认的UICollectionViewCell结构上相对比较简单,由下至上:</p>
<ul>
<li>首先是cell本身作为容器view</li>
<li>然后是一个大小自动适应整个cell的backgroundView,用作cell平时的背景</li>
<li>在其上是selectedBackgroundView,是cell被选中时的背景</li>
<li>最后是一个contentView,自定义内容应被加在这个view上</li>
</ul>
<h3 id="UICollectionViewLayout"><a href="#UICollectionViewLayout" class="headerlink" title="UICollectionViewLayout"></a>UICollectionViewLayout</h3><p>终于到UICollectionView的精髓了…这也是UICollectionView和UITableView最大的不同。UICollectionViewLayout可以说是UICollectionView的大脑和中枢,Layout决定了UICollectionView是如何显示在界面上的, 每个cell view、supplemental view和decoration view 都有layout属性。想要知道layouts如何灵活,只需看看 UICollectionViewLayoutAttributes 对象的特性就知道了:</p>
<ul>
<li>frame</li>
<li>center</li>
<li>size</li>
<li>transform3D</li>
<li>alpha</li>
<li>zIndex</li>
<li>hidden</li>
</ul>
<p>这是最酷的方法:</p>
<ul>
<li>-layoutAttributesForElementsInRect:</li>
</ul>
<p>在展示之前,一般需要生成合适的UICollectionViewLayout子类对象,并将其赋予CollectionView的collectionViewLayout属性。</p>
<h3 id="自定义layout"><a href="#自定义layout" class="headerlink" title="自定义layout"></a>自定义layout</h3><h4 id="继承UICollectionViewLayout"><a href="#继承UICollectionViewLayout" class="headerlink" title="继承UICollectionViewLayout"></a>继承UICollectionViewLayout</h4><h5 id="理解layout的处理过程"><a href="#理解layout的处理过程" class="headerlink" title="理解layout的处理过程"></a>理解layout的处理过程</h5><ol>
<li>prepareLayout 提供layout信息的一些前期准备</li>
<li>collectionViewContentSize 基于初始化计算得出的整个内容的size</li>
<li>layoutAttributesForElementsInRect: 返回在指定rectangle区域的cells和views的attributes</li>
</ol>
<p>布置自定义内容:<br><img src="https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/Art/cv_layout_process_2x.png" alt=""></p>
<h5 id="创建Layout-Attributes"><a href="#创建Layout-Attributes" class="headerlink" title="创建Layout Attributes"></a>创建Layout Attributes</h5><p>用下面类方法创建UICollectionViewLayoutAttributes的类实例:</p>
<ul>
<li>-layoutAttributesForItemAtIndexPath:</li>
<li>-layoutAttributesForSupplementaryViewOfKind:atIndexPath:</li>
<li>-layoutAttributesForDecorationViewOfKind:atIndexPath:</li>
</ul>
<h5 id="prepareLayout"><a href="#prepareLayout" class="headerlink" title="prepareLayout"></a>prepareLayout</h5><p>layout处理前,有机会做一些初始化计算。</p>
<h5 id="在给定Rectangle区域提供Items的Layout-Attributes"><a href="#在给定Rectangle区域提供Items的Layout-Attributes" class="headerlink" title="在给定Rectangle区域提供Items的Layout Attributes"></a>在给定Rectangle区域提供Items的Layout Attributes</h5><p>在layout处理流程的最后一步,collectionView将会调用layoutAttributesForElementsInRect:。目的是为和指定rectangle交叉的每一个cell和supplementary、decoration视图提供layout attributes。</p>
<p>布局看得见的元素:<br><img src="https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/Art/cv_visible_elements_2x.png" alt=""></p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>跟UITableView有些类似,一个UICollectionView的实现包括两个必要部分:UICollectionViewDataSource和UICollectionViewLayout,和一个交互部分:UICollectionViewDelegate。而Apple给出的UICollectionViewFlowLayout已经是一个很强力的layout方案了。</p>
<h2 id="自定义layout几种实现-点击查看具体代码"><a href="#自定义layout几种实现-点击查看具体代码" class="headerlink" title="自定义layout几种实现(点击查看具体代码)"></a>自定义layout几种实现(<a href="https://github.com/meigesir/TTCollectionView.git" target="_blank" rel="external">点击查看具体代码</a>)</h2><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/home.gif" alt="自定义layout"></p>
<h3 id="1-无限轮播"><a href="#1-无限轮播" class="headerlink" title="1. 无限轮播"></a>1. 无限轮播</h3><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/InfiniteCarouse.gif" alt="无限轮播"></p>
<p>优点,相比ScrollView,可以重用cell,优化性能</p>
<h4 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h4><ol>
<li>严格意义上说并没有自定义layout,而是使用的UICollectionViewFlowLayout,设置水平滚动方向,设置minimumLineSpacing为0</li>
<li>collectionView:设置pagingEnabled为YES</li>
<li>以上可以达到轮播的目的,无限轮播实现方式,就是在第一张轮播视图的前面插入最后一张轮播,最后一张轮播视图的后面插入第一张轮播,这样在滑动到第一个或最后一个位置的时候,分别无动画的切换到原始数据的最后一张或第一张。再加入timer定时滚动。</li>
</ol>
<h3 id="2-瀑布流(CHTCollectionViewWaterfallLayout)"><a href="#2-瀑布流(CHTCollectionViewWaterfallLayout)" class="headerlink" title="2. 瀑布流(CHTCollectionViewWaterfallLayout)"></a>2. 瀑布流(CHTCollectionViewWaterfallLayout)</h3><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/WaterFall.gif" alt="瀑布流"></p>
<p>瀑布流比较有代表的是app是Pinterest。特点是,每个元素都是等宽不等高,而且每当排列一个元素的时候,都是从最短的那一列开始排。这里我就不重复造轮了,因为有一个比较好的开源项目(CHTCollectionViewWaterfallLayout,注释也很充分)。但是作者有一个地方有欠缺(CHTFloorCGFloat),但是可以忽略不计。</p>
<h4 id="实现-1"><a href="#实现-1" class="headerlink" title="实现"></a>实现</h4><ol>
<li>prepareLayout<br>计算好每一列的高度,计算每一个元素的Layout Attributes。作者在此方法最后有一个亮点,就是将Attributes每20个分组,后面调用layoutAttributesForElementsInRect:的时候使用,可以省掉一些运算,从而优化性能。</li>
<li>collectionViewContentSize<br>算出真个内容的高度,也就是最后一个section的列的高度(最后保持一致,因为已经展示完了)</li>
<li>layoutAttributesForElementsInRect:<br>先锁定Attributes组的范围,然后再具体求解,优化了性能。</li>
</ol>
<h3 id="3-弹性header"><a href="#3-弹性header" class="headerlink" title="3. 弹性header"></a>3. 弹性header</h3><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/StretchyHeader.gif" alt="弹性header"></p>
<p>下拉collectionView的时候,header可以被拉伸,从而可以更全面地查看图片更多细节,手势松开,又可以反弹到初始状态。</p>
<h4 id="实现-2"><a href="#实现-2" class="headerlink" title="实现"></a>实现</h4><ol>
<li>展示时,在layoutAttributesForElementsInRect:方法中获取header的attributes</li>
<li>然后设置attributes的y和height值,从而达到相应的效果</li>
<li>弹性:调用collectionView的setAlwaysBounceVertical:,参数为YES</li>
<li>设置图片展示方式为UIViewContentModeScaleAspectFill</li>
</ol>
<h3 id="4-水平滚动放大"><a href="#4-水平滚动放大" class="headerlink" title="4. 水平滚动放大"></a>4. 水平滚动放大</h3><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/SlideZoomIn.gif" alt="水平滚动放大"></p>
<p>水平滚动cell,当到屏幕中间的时候,放到最大,并会自动校正位置</p>
<h4 id="实现-3"><a href="#实现-3" class="headerlink" title="实现"></a>实现</h4><ol>
<li>展示时,layoutAttributesForElementsInRect:,设置每个item的Attributes,通过item中心点x和collectionView屏幕中心点的x值的间距来设置item的缩放</li>
<li>校正位置:重写targetContentOffsetForProposedContentOffset:withScrollingVelocity:,在item不在中心位置的时候自动居中</li>
</ol>
<h3 id="5-拖动排序item"><a href="#5-拖动排序item" class="headerlink" title="5. 拖动排序item"></a>5. 拖动排序item</h3><p><img src="https://github.com/meigesir/TTCollectionView/raw/master/Resources/ReOrder.gif" alt="拖动排序item"></p>
<p>手动长按item的时候,item稍微放大一些,提示用户当前可以做出拖动操作。然后移动item,可以将item任意的移动位置。iOS9已经有相应的API支持,而且比较简单,这里为了兼容iOS7以上,所以需要自定义layout。由于也有相应的轮子LXReorderableCollectionViewFlowLayout,这里就不重新造轮子了,局限是不适用于自定义layout。</p>
<h3 id="实现-4"><a href="#实现-4" class="headerlink" title="实现"></a>实现</h3><ol>
<li>添加长按手势,有可能手势冲突,比如iOS9添加长按手势实现移动元素,所以需要设置我们自定义长按手势优先级高(requireGestureRecognizerToFail:)。</li>
<li>长按手势开始时,基于原有item的frame创建view,添加正常、高亮时的截图,然后放大view到1.1倍;长按手势结束时,view缩放到正常大小,然后view设置nil,拖动结束;两次相应的委托调用。</li>
<li>拖动需要添加pan手势,拖动改变时,改变view的中心点即可。</li>
<li>在layoutAttributesForElementsInRect:中,判断如果是当前操作的item,Attributes的hidden设为YES,从而隐藏原有的item。</li>
<li>invalidateLayoutIfNecessary,实现没有操作在item上面时不生效,及其相应的删除、插入操作,及其相应的委托方法。</li>
</ol>
<p>参考:</p>
<ol>
<li><a href="http://nshipster.cn/uicollectionview/" target="_blank" rel="external">UICollectionView</a></li>
<li><a href="https://onevcat.com/2012/06/introducing-collection-views/" target="_blank" rel="external">WWDC 2012 Session笔记——205 Introducing Collection Views</a></li>
<li><a href="https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html" target="_blank" rel="external">Creating Custom Layouts</a></li>
<li><a href="http://pandajohn.com/jin-bu-li-jie-uiscrollviewde-san-ge-shu-xing-contentoffset-contentsizeyi-ji-contentinset/" target="_blank" rel="external">理解UIScrollView的三个属性:contentOffset、contentSize以及contentInset</a></li>
<li><a href="https://nrj.io/stretchy-uicollectionview-headers/" target="_blank" rel="external">Stretchy UICollectionView headers</a></li>
</ol>
<p>自定义layout前,先来看看UICollectionView。</p>
<h2 id="什么是UICollectionView"><a href="#什么是UICollectionView" class="headerlink" title="什么是UICollectionView"></a>什么是UICollectionView</h2><p>UICollectionView是一种新的数据展示方式,简单来说可以把他理解成多列的UITableView(请一定注意这是UICollectionView的最最简单的形式)。</p>
swift网站资源收集
http://meigesir.github.io/2015/01/24/swift-site-gather/
2015-01-24T06:13:54.000Z
2016-06-14T18:02:00.000Z
<p>只保证收集到的绝对是干货,毕竟博主免不了会忽略掉一些干货,欢迎各位告知~</p>
<a id="more"></a>
<h2 id="swift语言学习"><a href="#swift语言学习" class="headerlink" title="swift语言学习"></a>swift语言学习</h2><ul>
<li><p><a href="http://numbbbbb.gitbooks.io/-the-swift-programming-language-/" target="_blank" rel="external">swift官方语言教程翻译中文版</a></p>
</li>
<li><p>对swift语言一定理解后,可以看下大牛王巍的<a href="http://swifter.tips/" target="_blank" rel="external">100个tips</a></p>
</li>
</ul>
<h2 id="swift工具站点"><a href="#swift工具站点" class="headerlink" title="swift工具站点"></a>swift工具站点</h2><ul>
<li><p><a href="http://www.swifttoolbox.io/" target="_blank" rel="external">Swift ToolBox</a>: 收录使用Swift所写的资源库</p>
</li>
<li><p><a href="http://swiftdoc.org/" target="_blank" rel="external">Swift 在线文档</a></p>
</li>
</ul>
<h2 id="IOS系统学习的站点"><a href="#IOS系统学习的站点" class="headerlink" title="IOS系统学习的站点"></a>IOS系统学习的站点</h2><ul>
<li><p>NSHipster:主要涉及IOS开发容易忽视的点: <a href="http://nshipster.cn/" target="_blank" rel="external">中文版</a> <a href="http://nshipster.com/" target="_blank" rel="external">英文版</a></p>
</li>
<li><p>objc:系统学习IOS开发的好地方: <a href="http://objccn.io" target="_blank" rel="external">中文版</a> <a href="http://www.objc.io/" target="_blank" rel="external">英文版</a></p>
</li>
</ul>
<h2 id="swift周订阅"><a href="#swift周订阅" class="headerlink" title="swift周订阅"></a>swift周订阅</h2><ul>
<li><p><a href="https://iosdevweekly.com/" target="_blank" rel="external">iOS Dev Weekly</a></p>
</li>
<li><p><a href="http://swiftsandbox.io/" target="_blank" rel="external">Swift Sandbox</a></p>
</li>
</ul>
<h2 id="tutorial"><a href="#tutorial" class="headerlink" title="tutorial"></a>tutorial</h2><ul>
<li><a href="http://www.appcoda.com/" target="_blank" rel="external">AppCoda</a></li>
<li><a href="https://developer.apple.com/videos/" target="_blank" rel="external">WWDC Session Videos</a></li>
</ul>
<p>只保证收集到的绝对是干货,毕竟博主免不了会忽略掉一些干货,欢迎各位告知~</p>