我是看他人的博客复写的一份demo,不足之处多多指教,不多说,先贴代码!
1、创建了一个 CircleLayout 继承UICollectionViewFlowLayout 类。
CircleLayout.h文件代码
#import <UIKit/UIKit.h>
@interface CircleLayout : UICollectionViewFlowLayout
//中心
@property (nonatomic, assign) CGPoint center;
//半径
@property (nonatomic, assign) CGFloat radius;
//cell数量
@property (nonatomic, assign) NSInteger cellCount;
@end
CircleLayout.m文件代码
#import "CircleLayout.h"
#define ITEM_SIZE (50.0f)
@interface CircleLayout ()
@property (nonatomic, strong) NSMutableArray *deleteIndexPaths;
@property (nonatomic, strong) NSMutableArray *insertIndexPaths;
@end
@implementation CircleLayout
//(第一步)布局准备中定义了一些之后计算所需要用到的参数。
//其实,_center 和 _radius 也可以放在 init 方法里面,但是 prepareLayout 具有更大的灵活性,因为每次重新给出一个layout时都会掉用prepareLayout,这样的如果有collectionView的大小变化需求时会自动适应变化。
-(void)prepareLayout{
//和init相似,必须call super的prepareLayout以保证初始化正确
[super prepareLayout];
CGSize size = self.collectionView.frame.size;
//水平移动,但是不知道为什么不能滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_cellCount = [[self collectionView] numberOfItemsInSection:0];
//控制cell所在圆圈的中心点坐标
_center = CGPointMake(size.width / 2.0, size.height / 1.5);
//控制cell所在的圆圈的大小
_radius = MIN(size.width, size.height) / 4;
}
//(第二步)按照UICollectionViewLayout子类的要求,重载了所需要的方法:
//整个collectionView的内容大小就是collectionView的大小(没有滚动)
-(CGSize) collectionViewContentSize
{
return [self collectionView].frame.size;
}
//(第三步)通过所在的indexPath确定位置
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
//生成空白的attributes对象,其中只记录了类型是cell以及对应的位置是indexPath
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//配置attributes到圆周上
attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
attributes.center = CGPointMake(_center.x + _radius * cosf(2 * indexPath.item * M_PI / _cellCount), _center.y + _radius * sinf(2 * indexPath.item * M_PI / _cellCount));
return attributes;
}
//(第四步)用来在一开始给出一套UICollectionViewLayoutAttributes
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attributes = [NSMutableArray array];
for(NSInteger i = 0; i < _cellCount; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}
//插入前,cell在圆心位置,全透明(不过当前方法已经被弃用,用下面的prepareForCollectionViewUpdates方法)
#if 0
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
attributes.alpha = 0.0;
attributes.center = CGPointMake(_center.x, _center.y);
return attributes;
}
#endif
//更新UICollectionViewCell调用的方法(删除、插入、移动...)
-(void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems
{
[super prepareForCollectionViewUpdates:updateItems];
self.deleteIndexPaths = [NSMutableArray array];
self.insertIndexPaths = [NSMutableArray array];
for(UICollectionViewUpdateItem *update in updateItems){
//删除事件
if (update.updateAction == UICollectionUpdateActionDelete) {
[self.deleteIndexPaths addObject:update.indexPathBeforeUpdate];
}
//插入事件
else if (update.updateAction == UICollectionUpdateActionInsert){
[self.insertIndexPaths addObject:update.indexPathAfterUpdate];
}
}
}
-(void)finalizeCollectionViewUpdates
{
[super finalizeCollectionViewUpdates];
self.deleteIndexPaths = nil;
self.insertIndexPaths = nil;
}
//插入
-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
if ([self.insertIndexPaths containsObject:itemIndexPath]) {
if (!attributes) {
attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
attributes.alpha = 0.0;
attributes.center = CGPointMake(_center.x, _center.y);
}
}
return attributes;
}
//删除
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath];
if ([self.deleteIndexPaths containsObject:itemIndexPath])
{
if (!attributes)
attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
attributes.alpha = 0.0;
attributes.center = CGPointMake(_center.x, _center.y);
//消失的一个动画效果
attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
}
return attributes;
}
@end
写了一个Cell类,继承UICollectionViewCell类
cell.h文件代码
#import <UIKit/UIKit.h>
@interface Cell : UICollectionViewCell
@property (nonatomic, strong) UILabel *label;
@end
cell.m文件代码
#import "Cell.h"
@implementation Cell
-(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
UIView *view = [[UIView alloc] initWithFrame:self.bounds];
view.backgroundColor = [UIColor purpleColor];
view.layer.cornerRadius = self.bounds.size.width / 2;
[self.contentView addSubview:view];
self.label = [[UILabel alloc] initWithFrame:CGRectMake(view.center.x - 10, view.center.y - 10, 20, 20)];
self.label.textAlignment = NSTextAlignmentCenter;
self.label.textColor = [UIColor whiteColor];
self.label.backgroundColor = [UIColor clearColor];
[view addSubview:self.label];
}
return self;
}
@end
#import "ViewController.h"
#import "CircleLayout.h"
#import "Cell.h"
@interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (assign, nonatomic) NSInteger cellCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
CircleLayout *layout = [[CircleLayout alloc] init];
self.cellCount = 5;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 200, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 400) collectionViewLayout:layout];
self.collectionView.backgroundColor = [UIColor grayColor];
self.collectionView.dataSource = self;
self.collectionView.delegate =self;
self.collectionView.userInteractionEnabled = YES;
self.collectionView.scrollEnabled = YES;
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"my_cell_id"];
[self.view addSubview:self.collectionView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self.collectionView addGestureRecognizer:tap];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.cellCount;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"my_cell_id" forIndexPath:indexPath];
cell.label.text = [NSString stringWithFormat:@"%ld", indexPath.row];
return cell;
}
-(void)tapAction:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
CGPoint initialPinchPoint = [sender locationInView:self.collectionView];
NSIndexPath* tappedCellPath = [self.collectionView indexPathForItemAtPoint:initialPinchPoint];
if (tappedCellPath!=nil)
{
self.cellCount = self.cellCount - 1;
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:tappedCellPath]];
} completion:nil];
}
else
{
self.cellCount = self.cellCount + 1;
[self.collectionView performBatchUpdates:^{
[self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:0 inSection:0]]];
} completion:nil];
}
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
http://blog.csdn.net/majiakun1/article/details/17204921