最近上班比较无聊,闲来无事就在网上随便下项目看。数组
今天就来看看自定义瀑布流布局。布局
自定义瀑布流布局主要是新建一个继承自UICollectionViewFlowLayout的类,重点是实现该类中的一个方法:spa
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 在这个方法里面,咱们要算出每一个item的文字和尺寸并返回给系统;code
当该类被咱们调用时系统会依次执行下列方法:blog
(1)- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds :当collectionView的显示范围发生改变的时候,是否须要从新刷新布局
一旦从新刷新布局,就会调用下面两个方法;继承
(2)- (void)prepareLayout :咱们通常在这里执行一些初始化的操做图片
(3)- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 在这个方法里面,咱们要算出每一个item的文字和尺寸并赋值给每个 UICollectionViewLayoutAttributes,而后返回给系统, 系统根据这个数组的布局属性展现collectionView,到这里自定义就搞定了。ci
固然,在这里咱们也能够监听下面这个方法来控制congtenoffset:get
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocityit
下面现学现卖,自定义布局实现以前项目的一个功能:
以前的一个项目有一个需求:要求作成以下的分页效果
毫无疑问,这个功能确定用UICollectionView来搞定它,可是难点就是这种不连续的分页效果,作起来比较麻烦。以前不知道重写UICollectionViewFlowLayout,因而在控制器里面直接监听- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 这个方法,这算起来就十分蛋疼了,不行你能够试着玩玩。
可是!重点来了,若是经过继承UICollectionViewFlowLayout自定义一个布局,在这里面监听上面那个方法,那就爽歪歪了。咱们能够轻松地拿到系统算好的布局,在这个布局的基础上作微调就能够了,核心代码就几句话:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{ CGRect rect; rect.origin.x = proposedContentOffset.x; rect.origin.y = 0; rect.size = self.collectionView.frame.size; NSArray *array = [super layoutAttributesForElementsInRect:rect]; CGFloat collectionCenterX = self.collectionView.frame.size.width*0.5 + proposedContentOffset.x; CGFloat minDelta = MAXFLOAT; // 核心:判断collectionView的中心离哪一个item更近就让那个item显示在中央 for (UICollectionViewLayoutAttributes *attrs in array) { if (fabs(minDelta)>fabs(attrs.center.x-collectionCenterX)) { minDelta = attrs.center.x-collectionCenterX; } } proposedContentOffset.x+=minDelta; return proposedContentOffset; }
这里咱们只是拿到系统算好的布局再作偏移,因此没必要从新算布局。
若是要作想天猫商品展现不等高的界面,如图:
这种界面的思路就是布局固定两列,遍历商品数据逐个把商品加到列高比较小的那一列,算出各个item的布局属性(咱们必须知道图片的宽高比),这种算起来就稍微麻烦一点了。