//
// CircleLayout.m
// UICollectionViewTest
//
// Created by wjr on 2019/3/4.
// Copyright © 2019 wjr. All rights reserved.
//
#import "CircleLayout.h"
@interface CircleLayout()
@property(nonatomic,strong) NSMutableArray* attrsAry;
@property (nonatomic, strong) NSMutableArray *deleteIndexPaths;
@property (nonatomic, strong) NSMutableArray *insertIndexPaths;
@end
@implementation CircleLayout
-(void)prepareLayout
{
[super prepareLayout];
if (self.attrsAry == nil)
self.attrsAry = [[NSMutableArray alloc] init];
[self.attrsAry removeAllObjects];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (int i = 0; i < count; i++)
{
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes* attr = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attrsAry addObject:attr];
}
}
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
//NSLog(@"1");
return self.attrsAry;
}
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger count = [self.collectionView numberOfItemsInSection:0];
CGFloat radius = 180;
CGFloat ox = self.collectionView.frame.size.width * 0.5;
CGFloat oy = self.collectionView.frame.size.height * 0.5;
CGFloat angle = 2 * M_PI * indexPath.item / count;
CGFloat centerX = ox + radius*cos(angle);
CGFloat centerY = oy + radius*sin(angle);
UICollectionViewLayoutAttributes* attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.center = CGPointMake(centerX, centerY);
attrs.size = CGSizeMake(50, 50);
return attrs;
}
- (NSIndexPath *)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position
{
//NSLog(@"target row = %ld,section=%ld",previousIndexPath.row,previousIndexPath.section);
return [self.collectionView indexPathForItemAtPoint:position];
return [self getPath:position];
return [NSIndexPath indexPathForRow:9 inSection:0];
}
-(NSIndexPath*)getPath:(CGPoint)position
{
for (int i = 0; i < self.attrsAry.count; i++)
{
UICollectionViewLayoutAttributes* attr = [self.attrsAry objectAtIndex:i];
if (CGRectContainsPoint(attr.frame,position))
{
return attr.indexPath;
}
}
return nil;
}
-(CGSize)collectionViewContentSize
{
return CGSizeMake(500, 500);
}
- (void)prepareForCollectionViewUpdates:(NSArray *)updateItems
{
// Keep track of insert and delete index paths
[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];
// release the insert and delete index paths
self.deleteIndexPaths = nil;
self.insertIndexPaths = nil;
}
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
// Must call super
UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
if ([self.insertIndexPaths containsObject:itemIndexPath])
{
// only change attributes on inserted cells
if (!attributes)
attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
// Configure attributes ...
attributes.alpha = 0.0;
CGFloat ox = self.collectionView.frame.size.width * 0.5;
CGFloat oy = self.collectionView.frame.size.height * 0.5;
attributes.center = CGPointMake(ox, oy);
}
return attributes;
}
// Note: name of method changed
// Also this gets called for all visible cells (not just the deleted ones) and
// even gets called when inserting cells!
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
// So far, calling super hasn't been strictly necessary here, but leaving it in
// for good measure
UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath];
if ([self.deleteIndexPaths containsObject:itemIndexPath])
{
// only change attributes on deleted cells
if (!attributes)
attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
// Configure attributes ...
attributes.alpha = 0.0;
CGFloat ox = self.collectionView.frame.size.width * 0.5;
CGFloat oy = self.collectionView.frame.size.height * 0.5;
attributes.center = CGPointMake(ox, oy);
}
return attributes;
}
@end
ViewController
//
// ViewController.m
// UICollectionViewTest
//
// Created by wjr on 16/6/2.
// Copyright © 2016年 wjr. All rights reserved.
//
#import "ViewController.h"
#import "CircleLayout.h"
@interface ViewController ()
@property(nonatomic,strong) NSMutableArray* imageAry;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CircleLayout* layout = [[CircleLayout alloc] init];
//UICollectionViewFlowLayout* layouts = [[UICollectionViewFlowLayout alloc] init];
//layouts.scrollDirection = UICollectionViewScrollDirectionVertical;
CGSize size = self.view.bounds.size;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 44 + 50, size.width, size.height - 44 - 50) collectionViewLayout:layout];
self.collectionView.backgroundColor = [UIColor orangeColor];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
[self.collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
[self.view addSubview:self.collectionView];
UILongPressGestureRecognizer *longpress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
longpress.minimumPressDuration = 0.5;
[self.collectionView addGestureRecognizer:longpress];
self.imageAry = [[NSMutableArray alloc] init];
int index = 1;
for (int i = 0; i < 10; i++)
{
NSDictionary* dic = @{@"image":[NSString stringWithFormat:@"%d.png",index],@"text":[NSString stringWithFormat:@"%d",i]};
[self.imageAry addObject:dic];
index++;
if (index > 11) {
index=1;
}
}
UIButton* button = [UIButton new];
[button setFrame:CGRectMake(0, 44, 100, 50)];
[button setTitle:@"添加" forState:UIControlStateNormal];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(add) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
button = [UIButton new];
[button setFrame:CGRectMake(110, 44, 100, 50)];
[button setTitle:@"删除" forState:UIControlStateNormal];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(remove) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
-(void)add
{
int index = (int)self.imageAry.count;
NSDictionary* dic = @{@"image":[NSString stringWithFormat:@"%d.png",1],@"text":[NSString stringWithFormat:@"%d",index]};
[self.imageAry insertObject:dic atIndex:0];
[self.collectionView performBatchUpdates:^{
[self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:0 inSection:0]]];
} completion:nil];
}
-(void)remove
{
int index = (int)self.imageAry.count - 1;
[self.imageAry removeObjectAtIndex:index];
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:index inSection:0]]];
} completion:nil];
}
-(void)longPress:(UILongPressGestureRecognizer*)recognizer
{
switch (recognizer.state) {
case UIGestureRecognizerStateBegan: {
[self handleEditingMoveWhenGestureBegan:recognizer];
break;
}
case UIGestureRecognizerStateChanged: {
[self handleEditingMoveWhenGestureChanged:recognizer];
break;
}
case UIGestureRecognizerStateEnded: {
[self handleEditingMoveWhenGestureEnded:recognizer];
break;
}
default: {
[self handleEditingMoveWhenGestureCanceledOrFailed:recognizer];
break;
}
}
}
- (void)handleEditingMoveWhenGestureBegan:(UILongPressGestureRecognizer *)recognizer{
CGPoint pressPoint = [recognizer locationInView:self.collectionView];
NSIndexPath* selectIndexPath = [self.collectionView indexPathForItemAtPoint:pressPoint];
//MyCollectionViewCell *cell = (MyCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:selectIndexPath];
[self.collectionView beginInteractiveMovementForItemAtIndexPath:selectIndexPath];
}
- (void)handleEditingMoveWhenGestureChanged:(UILongPressGestureRecognizer *)recognizer{
CGPoint pressPoint = [recognizer locationInView:self.collectionView];
[self.collectionView updateInteractiveMovementTargetPosition:pressPoint];
}
- (void)handleEditingMoveWhenGestureEnded:(UILongPressGestureRecognizer *)recognizer{
[self.collectionView endInteractiveMovement];
}
- (void)handleEditingMoveWhenGestureCanceledOrFailed:(UILongPressGestureRecognizer *)recognizer{
CGPoint pressPoint = [recognizer locationInView:self.collectionView];
[self.collectionView cancelInteractiveMovement];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.imageAry.count;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
NSInteger section = [indexPath section];
MyCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
NSDictionary* dic = [self.imageAry objectAtIndex:row];
cell.imageView.image = [UIImage imageNamed:[dic objectForKey:@"image"]];
cell.textView.text = [dic objectForKey:@"text"];
return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
return CGSizeMake(50, 50);
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(20, 20, 20, 20);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
NSInteger section = [indexPath section];
[self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
NSLog(@"选中了 %ld,%ld",section,row);
}
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor greenColor];
}
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor blueColor];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
int screenWidth = [[UIScreen mainScreen] bounds].size.width;
return (CGSize){screenWidth,44};
}
//- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
//{
//
// if([kind isEqualToString:UICollectionElementKindSectionHeader])
// {
// MyCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
// if(headerView == nil)
// {
// headerView = [[MyCollectionReusableView alloc] init];
// }
// headerView.backgroundColor = [UIColor grayColor];
//
// return headerView;
// }
// else if([kind isEqualToString:UICollectionElementKindSectionFooter])
// {
//
// }
//
// return nil;
//}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 50;
}
//// copy and paste 的实现
//- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender
//{
// if([NSStringFromSelector(action) isEqualToString:@"copy:"])
// {
// // NSLog(@"-------------执行拷贝-------------");
// [collectionView performBatchUpdates:^{
// NSLog(@"33");
// } completion:nil];
// }
// else if([NSStringFromSelector(action) isEqualToString:@"paste:"])
// {
// NSLog(@"-------------执行粘贴-------------");
// }
//}
//- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
//{
// return TRUE;
//}
//- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender
//{
// if([NSStringFromSelector(action) isEqualToString:@"copy:"])
// {
// return YES;
// }
// else if([NSStringFromSelector(action) isEqualToString:@"paste:"])
// {
// return YES;
// }
// return NO;
//}
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath
{
if (sourceIndexPath.item > destinationIndexPath.item )
{
NSString* text = [self.imageAry objectAtIndex:sourceIndexPath.item];
[self.imageAry removeObjectAtIndex:sourceIndexPath.item];
[self.imageAry insertObject:text atIndex:destinationIndexPath.item];
}
else
{
[self.imageAry exchangeObjectAtIndex:sourceIndexPath.item withObjectAtIndex:destinationIndexPath.item];
}
NSLog(@"%@",self.imageAry);
}
@end