#import <UIKit/UIKit.h>
@interface WQViewController : UIViewController
- (id)initWithFrame:(CGRect)frame;
@end
#import "WQViewController.h"
#import "WQCollectionViewController.h"
#import "WQCollectionViewCircleLayout.h"
@interface WQViewController ()
@end
@implementation WQViewController
- (id)initWithFrame:(CGRect)frame {
if (self == [super init]) {
self.view.frame = frame;
self.view.backgroundColor = [UIColor yellowColor];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
WQCollectionViewCircleLayout *circleLayout = [[WQCollectionViewCircleLayout alloc] init];
WQCollectionViewController *collectionVC = [[WQCollectionViewController alloc] initWithCollectionViewLayout:circleLayout];
[self addChildViewController:collectionVC];
[self.view addSubview:collectionVC.collectionView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
~~~~~~~~~~~~~~~~~~~~~~~
#import <UIKit/UIKit.h>
@interface WQCollectionViewController : UICollectionViewController
@end
#import "WQCollectionViewController.h"
#import "WQCollectionViewCircleLayout.h"
#import "WQCollectionViewCell.h"
@interface WQCollectionViewController ()
@property (assign, nonatomic) NSInteger cellCount;
@end
@implementation WQCollectionViewController
static NSString * const reuseIdentifier = @"Cell";
- (void)viewDidLoad {
[super viewDidLoad];
_cellCount = 8;
self.collectionView.frame = [UIScreen mainScreen].bounds;
self.collectionView.backgroundColor = [UIColor whiteColor];
[self.collectionView registerClass:[WQCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[self.collectionView addGestureRecognizer:tapGesture];
}
#pragma mark - UITapGesture
- (void)handleTapGesture:(UITapGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
CGPoint initiailPinchPoint = [sender locationInView:self.collectionView];
NSIndexPath *tapCellPath = [self.collectionView indexPathForItemAtPoint:initiailPinchPoint];
if (tapCellPath != nil) {
[self.collectionView performBatchUpdates:^{
self.cellCount = self.cellCount - 1;
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:tapCellPath]];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
} else {
[self.collectionView performBatchUpdates:^{
self.cellCount = self.cellCount + 1;
[self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:(random()%self.cellCount) inSection:0]]];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
}
}
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _cellCount;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
WQCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[cell updateAppreanceAccrodingToItem:indexPath.item];
cell.contentView.backgroundColor = [UIColor redColor];
cell.contentView.layer.cornerRadius = 20;
cell.contentView.layer.masksToBounds = YES;
// UILabel *lbl = [[UILabel alloc] init];
// lbl.center = cell.contentView.center;
// lbl.text = [NSString stringWithFormat:@"%ld", indexPath.item];
// [lbl sizeToFit];
// [cell.contentView addSubview:lbl];
//
return cell;
}
#pragma mark <UICollectionViewDelegate>
/*
// Uncomment this method to specify if the specified item should be highlighted during tracking
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
*/
/*
// Uncomment this method to specify if the specified item should be selected
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
*/
/*
// Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
return NO;
}
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
}
*/
@end
~~~~~~~~~~~~~~~~~~~~~~~~
#import <UIKit/UIKit.h>
@interface WQCollectionViewCell : UICollectionViewCell
- (void)updateAppreanceAccrodingToItem:(NSInteger)item;
@end
#import "WQCollectionViewCell.h"
@interface WQCollectionViewCell ()
@property(strong, nonatomic)UILabel *lbl;
@end
@implementation WQCollectionViewCell
-(void)prepareForReuse {
_lbl.text = nil;
}
- (void)updateAppreanceAccrodingToItem:(NSInteger)item {
self.lbl.text = [NSString stringWithFormat:@"%ld", item];
[self addSubview:self.lbl];
}
- (UILabel *)lbl {
if (_lbl == nil) {
_lbl = [[UILabel alloc] init];
[_lbl setFont:[UIFont systemFontOfSize:12.0f]];
_lbl.textAlignment = NSTextAlignmentCenter;
_lbl.frame = CGRectMake(10, 10, 20, 20);
}
return _lbl;
}
@end
~~~~~~~~~~~~~~~~~~~~~自定义layout
#import <UIKit/UIKit.h>
@interface WQCollectionViewCircleLayout : UICollectionViewLayout
@end
#define ITEM_SIZE 40.0f
#import "WQCollectionViewCircleLayout.h"
@interface WQCollectionViewCircleLayout ()
@property(assign, nonatomic) NSInteger cellCount;
@property(assign, nonatomic) CGPoint center;
@property(assign, nonatomic) CGFloat radius;
@property(strong, nonatomic) NSMutableArray *indexPathToAnimation;
@end
@implementation WQCollectionViewCircleLayout
- (void)prepareLayout {
[super prepareLayout];
CGSize size = self.collectionView.frame.size;
_cellCount = [self.collectionView numberOfItemsInSection:0];
_center = CGPointMake(size.width/2.0f, size.height/2.0f);
// _radius = MIN(size.width/2.5f, size.height/2.5f);
_radius = 120;
}
- (CGSize)collectionViewContentSize {
return self.collectionView.frame.size;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *attributes = [NSMutableArray array];
for (int i = 0; i < _cellCount; i ++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
CGRect oldBounds = self.collectionView.bounds;
if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds) || CGRectGetHeight(newBounds) != CGRectGetWidth(oldBounds)) {
return YES;
}
return NO;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
layoutAttributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
layoutAttributes.center = CGPointMake(_center.x + _radius * cosf(2*indexPath.item*M_PI / _cellCount), _center.y + _radius * sinf(2*indexPath.item*M_PI / _cellCount));
NSLog(@"%@", NSStringFromCGRect(layoutAttributes.frame));
return layoutAttributes;
}
-(void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems {
[super prepareForCollectionViewUpdates:updateItems];
NSMutableArray *attrsArray = [NSMutableArray array];
for (UICollectionViewUpdateItem *updateItem in updateItems) {
switch (updateItem.updateAction) {
case UICollectionUpdateActionInsert:
{
NSIndexPath *itemIndex = updateItem.indexPathAfterUpdate;
[attrsArray addObject:itemIndex];
}
break;
case UICollectionUpdateActionDelete:
{
NSIndexPath *itemIndex = updateItem.indexPathBeforeUpdate;
[attrsArray addObject:itemIndex];
}
break;
case UICollectionUpdateActionMove:
{
NSIndexPath *itemIndexBeforeUpdate = updateItem.indexPathBeforeUpdate;
NSIndexPath *itemIndexAfterUpdate = updateItem.indexPathAfterUpdate;
[attrsArray addObject:itemIndexBeforeUpdate];
[attrsArray addObject:itemIndexAfterUpdate];
}
break;
case UICollectionUpdateActionReload:
break;
case UICollectionUpdateActionNone:
break;
default:
break;
}
}
_indexPathToAnimation = attrsArray;
}
-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
UICollectionViewLayoutAttributes *layoutAttr = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
if ([_indexPathToAnimation containsObject:itemIndexPath]) {
layoutAttr.transform = CGAffineTransformRotate(CGAffineTransformMakeScale(0.2, 0.2), M_PI);
layoutAttr.center = CGPointMake(self.collectionView.center.x, self.collectionView.bounds.size.height);
// layoutAttr.center = CGPointMake(CGRectGetMidX(self.collectionView.bounds), CGRectGetMidY(self.collectionView.bounds));
[self.indexPathToAnimation removeObject:itemIndexPath];
}
return layoutAttr;
}
@end
~~~~~~~~~~~~~实现效果: