UICollectionViewLayout——layout实现圆形布局
UICollectionViewLayout子类
基本方法
UICollectionView 和 UITableView 最重要的区别就是 UICollectionView 并不知道如何布局,它把布局机制委托给了 UICollectionViewLayout 子类,默认的布局方式是 UICollectionFlowViewLayout 类提供的流式布局。不过也可以创建自己的布局方式,通过继承 UICollectionViewLayout。
子类需要覆盖父类以下3个方法:
- prepareLayout
- layoutAttributesForElementsInRect:(CGRect)rect
- collectionViewContentSize
- (void)prepareLayout
初始化参数,只会调动一次,可以设置每个块的属性,可设置的属性包括:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| //配置item的布局位置 @property (nonatomic) CGRect frame; //配置item的中心 @property (nonatomic) CGPoint center; //配置item的尺寸 @property (nonatomic) CGSize size; //配置item的3D效果 @property (nonatomic) CATransform3D transform3D; //配置item的bounds @property (nonatomic) CGRect bounds NS_AVAILABLE_IOS(7_0); //配置item的旋转 @property (nonatomic) CGAffineTransform transform NS_AVAILABLE_IOS(7_0); //配置item的alpha @property (nonatomic) CGFloat alpha; //配置item的z坐标 @property (nonatomic) NSInteger zIndex; // default is 0 //配置item的隐藏 @property (nonatomic, getter=isHidden) BOOL hidden; //item的indexpath @property (nonatomic, strong) NSIndexPath *indexPath; //获取item的类型 @property (nonatomic, readonly) UICollectionElementCategory representedElementCategory; @property (nonatomic, readonly, nullable) NSString *representedElementKind; //一些创建方法 + (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath; + (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath; + (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;
|
- (CGSize)collectionViewContentSize
布局首先要提供的信息就是滚动区域大小,这样collection view才能正确的管理滚动。布局对象必须在此时计算它内容的总大小,包括supplementary views和decoration views。
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
实现必须返回一个包含UICollectionViewLayoutAttributes对象的数组.其中包括:中心(center),尺寸(size),透明度(alpha),层级(zIndex),动画效果(transform3D),隐藏(hidden)等。UICollectionViewLayoutAttributes对象决定了cell的摆设位置(frame)。
传入参数rect是一个包含要显示区域的块。这个块的大小一般为2倍的collectionview的长度,只有滑动即将超过rect的范围,rect才会改变数值,保证了显示范围内的所有元素都在rect内。这个参数只是框定了显示范围,自定义layout的时候并不需要用到这个参数,而是使用contentOffset等属性,设置位置信息。
http://git.oschina.net/null_549_8696/criclelayout
CircleLayout.h
1 2 3 4 5
| #import <UIKit/UIKit.h>
@interface CircleLayout : UICollectionViewLayout
@end
|
CircleLayout.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #import "CircleLayout.h"
#define kScreenWidth [UIScreen mainScreen].bounds.size.width #define kScreenHeight [UIScreen mainScreen].bounds.size.height #define ITEM_SIZE 50
@interface CircleLayout(){ NSMutableArray<UICollectionViewLayoutAttributes *> * _attributeAttay; int _itemCount; //item 个数 }
@end
@implementation CircleLayout
- (void)prepareLayout { [super prepareLayout]; //获取item的个数 _itemCount = (int)[self.collectionView numberOfItemsInSection:0]; _attributeAttay = [[NSMutableArray alloc]init]; //先设定大圆的半径 取长和宽最短的 CGFloat radius = MIN(self.collectionView.frame.size.width, self.collectionView.frame.size.height)/2; //计算圆心位置 CGPoint center = CGPointMake(self.collectionView.frame.size.width/2, self.collectionView.frame.size.height/2); //设置每个item的大小为50*50 则半径为25 for (int i=0; i<_itemCount; i++) { UICollectionViewLayoutAttributes * attris = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; //设置item大小 attris.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE); //计算每个item的圆心位置 //算出的x y值还要减去item自身的半径大小 float x = center.x + cosf(2 * M_PI/_itemCount * i) * (radius - 50); float y = center.y + sinf(2 * M_PI/_itemCount * i) * (radius - 50); attris.center = CGPointMake(x, y); [_attributeAttay addObject:attris]; } } //设置内容区域的大小 -(CGSize)collectionViewContentSize{ return self.collectionView.frame.size; } //返回设置数组 -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ return _attributeAttay; }
@end
|
controller使用
1 2 3 4 5 6 7
| CircleLayout * layout = [[CircleLayout alloc]init]; UICollectionView * collect = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) collectionViewLayout:layout]; collect.delegate=self; collect.dataSource=self;
[collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"]; [self.view addSubview:collect];
|