UICollectionViewLayout——layout實(shí)現(xiàn)圓形布局
UICollectionViewLayout子類
http://git.oschina.net/null_549_8696/criclelayout
基本方法
UICollectionView 和 UITableView 最重要的區(qū)別就是 UICollectionView 并不知道如何布局著摔,它把布局機(jī)制委托給了 UICollectionViewLayout 子類溶褪,默認(rèn)的布局方式是 UICollectionFlowViewLayout 類提供的流式布局券腔。不過(guò)也可以創(chuàng)建自己的布局方式亿笤,通過(guò)繼承 UICollectionViewLayout。
子類需要覆蓋父類以下3個(gè)方法:
- prepareLayout
- layoutAttributesForElementsInRect:(CGRect)rect
- collectionViewContentSize
- (void)prepareLayout
初始化參數(shù),只會(huì)調(diào)動(dòng)一次蜀漆,可以設(shè)置每個(gè)塊的屬性,可設(shè)置的屬性包括:
//配置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的旋轉(zhuǎn)
@property (nonatomic) CGAffineTransform transform NS_AVAILABLE_IOS(7_0);
//配置item的alpha
@property (nonatomic) CGFloat alpha;
//配置item的z坐標(biāo)
@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;
//一些創(chuàng)建方法
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;
- (CGSize)collectionViewContentSize
布局首先要提供的信息就是滾動(dòng)區(qū)域大小,這樣collection view才能正確的管理滾動(dòng)左驾。布局對(duì)象必須在此時(shí)計(jì)算它內(nèi)容的總大小,包括supplementary views和decoration views极谊。
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
實(shí)現(xiàn)必須返回一個(gè)包含UICollectionViewLayoutAttributes對(duì)象的數(shù)組.其中包括:中心(center)诡右,尺寸(size),透明度(alpha)轻猖,層級(jí)(zIndex)帆吻,動(dòng)畫效果(transform3D),隱藏(hidden)等。UICollectionViewLayoutAttributes對(duì)象決定了cell的擺設(shè)位置(frame)咙边。
傳入?yún)?shù)rect是一個(gè)包含要顯示區(qū)域的塊猜煮。這個(gè)塊的大小一般為2倍的collectionview的長(zhǎng)度,只有滑動(dòng)即將超過(guò)rect的范圍败许,rect才會(huì)改變數(shù)值王带,保證了顯示范圍內(nèi)的所有元素都在rect內(nèi)。這個(gè)參數(shù)只是框定了顯示范圍市殷,自定義layout的時(shí)候并不需要用到這個(gè)參數(shù)愕撰,而是使用contentOffset等屬性,設(shè)置位置信息。
圓形布局實(shí)例
CircleLayout.h
#import <UIKit/UIKit.h>
@interface CircleLayout : UICollectionViewLayout
@end
CircleLayout.m
#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 個(gè)數(shù)
}
@end
@implementation CircleLayout
- (void)prepareLayout
{
[super prepareLayout];
//獲取item的個(gè)數(shù)
_itemCount = (int)[self.collectionView numberOfItemsInSection:0];
_attributeAttay = [[NSMutableArray alloc]init];
//先設(shè)定大圓的半徑 取長(zhǎng)和寬最短的
CGFloat radius = MIN(self.collectionView.frame.size.width, self.collectionView.frame.size.height)/2;
//計(jì)算圓心位置
CGPoint center = CGPointMake(self.collectionView.frame.size.width/2, self.collectionView.frame.size.height/2);
//設(shè)置每個(gè)item的大小為50*50 則半徑為25
for (int i=0; i<_itemCount; i++) {
UICollectionViewLayoutAttributes * attris = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
//設(shè)置item大小
attris.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
//計(jì)算每個(gè)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];
}
}
//設(shè)置內(nèi)容區(qū)域的大小
-(CGSize)collectionViewContentSize{
return self.collectionView.frame.size;
}
//返回設(shè)置數(shù)組
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
return _attributeAttay;
}
@end
controller使用
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];