#import "AppDelegate.h"
#import "CircleLayout.h"
#import "CollectionViewDataSource.h"
#import "MyCollectionReusableView.h"

@interface CircleLayout()
{
CGSize cvSize;
CGPoint cvCenter;
CGFloat radius;
NSInteger cellCount;
}

@property (strong, nonatomic) NSMutableArray *indexPathsToAnimate;

@end

@implementation CircleLayout

- (void)prepareLayout
{
[super prepareLayout];

[self registerClass:[MyCollectionReusableView class] forDecorationViewOfKind:@"MyDecoration"];

cvSize = self.collectionView.frame.size;
cellCount = [self.collectionView numberOfItemsInSection:0];
cvCenter = CGPointMake(cvSize.width / 2.0, cvSize.height / 2.0);
radius = MIN(cvSize.width, cvSize.height) / 2.5;
}

- (CGSize)collectionViewContentSize
{
return self.collectionView.bounds.size;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *array = [NSMutableArray array];

//add cells
for (int i=0; i<cellCount; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];

UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];

[array addObject:attributes];
}

//add first supplementaryView
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:@"FirstSupplementary" atIndexPath:indexPath];
[array addObject:attributes];

//add second supplementaryView
attributes = [self layoutAttributesForSupplementaryViewOfKind:@"SecondSupplementary" atIndexPath:indexPath];
[array addObject:attributes];

//add decorationView
attributes = [self layoutAttributesForDecorationViewOfKind:@"MyDecoration" atIndexPath:indexPath];
[array addObject:attributes];

return array;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

attributes.size = CGSizeMake(20, 20);
attributes.center = CGPointMake(cvCenter.x + radius * cosf(2 * indexPath.item * M_PI / cellCount),
cvCenter.y + radius * sinf(2 * indexPath.item * M_PI / cellCount));

return attributes;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];

attributes.size = CGSizeMake(260, 40);
if([elementKind isEqual:@"FirstSupplementary"])
{
attributes.center = CGPointMake(cvSize.width/2, 40);
}
else
{
attributes.center = CGPointMake(cvSize.width/2, cvSize.height-40);
}

return attributes;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath];

attributes.size = CGSizeMake(140, 40);
attributes.center = CGPointMake(cvSize.width/2, cvSize.height/2);

return attributes;
}

//当边界更改时是否更新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
CGRect oldBounds = self.collectionView.bounds;

if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds))
{
return YES;
}

return NO;
}

//通知布局,collection view里有元素即将改变,这里可以收集改变的元素indexPath和action类型。
-(void)prepareForCollectionViewUpdates:(NSArray *)updateItems
{
[super prepareForCollectionViewUpdates:updateItems];

NSMutableArray *indexPaths = [NSMutableArray array];

for(UICollectionViewUpdateItem *updateItem in updateItems)
{
//UICollectionUpdateActionInsert,
//UICollectionUpdateActionDelete,
//UICollectionUpdateActionReload,
//UICollectionUpdateActionMove,
//UICollectionUpdateActionNone

NSLog(@"before index:%d,after index:%d,action:%d", updateItem.indexPathBeforeUpdate.row,updateItem.indexPathAfterUpdate.row,updateItem.updateAction);

switch (updateItem.updateAction) {
case UICollectionUpdateActionInsert:
[indexPaths addObject:updateItem.indexPathAfterUpdate];
break;
case UICollectionUpdateActionDelete:
[indexPaths addObject:updateItem.indexPathBeforeUpdate];
break;
case UICollectionUpdateActionMove:
[indexPaths addObject:updateItem.indexPathBeforeUpdate];
[indexPaths addObject:updateItem.indexPathAfterUpdate];
break;
default:
NSLog(@"unhandled case: %@", updateItem);
break;
}
}

self.indexPathsToAnimate = indexPaths;
}

//当一个元素被插入collection view时,返回它的初始布局,这里可以加入一些动画效果。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:itemIndexPath];

if([self.indexPathsToAnimate containsObject:itemIndexPath])
{
attr.transform = CGAffineTransformRotate(CGAffineTransformMakeScale(10,10),M_PI);
attr.center = CGPointMake(CGRectGetMidX(self.collectionView.bounds), CGRectGetMidY(self.collectionView.bounds));
[self.indexPathsToAnimate removeObject:itemIndexPath];
}

return attr;
}

- (NSArray *)getLetterArray
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

return appDelegate.letterArray;
}

@end

CircleLayout.m

自定义UICollectionLayout的更多相关文章

  1. 自定义UICollectionLayout布局 —— UIKit之学习UICollectionView记录一《瀑布流》

    一.思路 思路一:比较每一行所有列的cell的高度,从上到下(也就是从第一行开始),从最短的开始计算,(记录下b的高度和索引,从开始计算,依次类推) 思路二:设置上.下.左.右间距和行间距.列间距及列 ...

  2. 自定义 ---UICollectionViewLayout-正N变形居中布局

    1. 自定义UICollectionLayout ---- 正三角形居中布局 支持多个图形的自动布局 2. 自定义UICollectionLayout ---- 正方形居中布局 滚动展示的区域 3.  ...

  3. 关于Unity3D自定义编辑器的学习

    被人物编辑器折腾了一个月,最终还是交了点成品上去(还要很多优化都还么做).  刚接手这项工作时觉得没概念,没想法,不知道.后来就去看<<Unity5.X从入门到精通>>中有关于 ...

  4. 一起学微软Power BI系列-使用技巧(5)自定义PowerBI时间日期表

    1.日期函数表作用 经常使用Excel或者PowerBI,Power Pivot做报表,时间日期是一个重要的纬度,加上做一些钻取,时间日期函数表不可避免.所以今天就给大家分享一个自定义的做日期表的方法 ...

  5. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  6. ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单

    前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...

  7. ASP.NET Aries 入门开发教程5:自定义列表页工具栏区

    前言: 抓紧时间,继续写教程,因为发现用户期待的内容,都在业务处理那一块. 不得不继续勤劳了. 这节主要介绍工具栏区的玩法. 工具栏的默认介绍: 工具栏默认包括5个按钮,根据不同的权限决定显示: 添加 ...

  8. UWP中实现自定义标题栏

    UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...

  9. JavaScript 自定义对象

    在Js中,除了Array.Date.Number等内置对象外,开发者可以通过Js代码创建自己的对象. 目录 1. 对象特性:描述对象的特性 2. 创建对象方式:对象直接量.new 构造函数.Objec ...

随机推荐

  1. D. Print a 1337-string...

    D. Print a 1337-string... 输出一个字符串 里面包含n个子序列 1337 #include<bits/stdc++.h> using namespace std; ...

  2. SQL语法——Join详解

    一.INNER JOIN 用法: select column_name(s) from table 1 INNER JOIN table 2 ON table 1.column_name=table ...

  3. Oracle报Ora01522

    应用服务报错截图 数据库后台日志报错截图 从日志分析应该是回滚异常造成表空间无法使用回滚段,而回滚涉及的表空间为undo表空间 尝试新建UNDO表空间,再将UNDO_TABLESPACE切换到新建的U ...

  4. onload,domcontentload区别+onload详解

    todo onLoad是的在页面所有文件加载完成后执行 DomContentLoad是Dom加载完成后执行,不必等待样式脚本和图片加载 domContentLoad更为合理, 原理: 如果是webki ...

  5. vue 路由懒加载 resolve vue-router配置

    使用方法 component:resolve => require(['@/pages/About'],resolve) //"@"相当于".." 懒加载 ...

  6. eclipse.ini中加入-vm

    1. 在eclipse.ini中添加两行     -vm     C:\Program Files\Java\jdk1.6.0_02\bin\javaw.exe     注意: 要写在两行,写在一行不 ...

  7. 关闭layer.open打开的页面

    window.parent.location.reload(); //刷新父页面 var index = parent.layer.getFrameIndex(window.name); //获取窗口 ...

  8. open jdk卸载

    //查找:open jdk # rpm -qa | grep java //卸载open jdk # rpm -e --nodeps 包 # source /etc/profile # java -v ...

  9. HTTP头详解:

      GET/mycode/2.gifHTTP/1.1 [表示发送的是GET请求,请求资源是/mycode/2.gif,协议HTTP/1.1] Host:localhost [主机] Connectio ...

  10. Vue知识整理10:条件渲染(v-if v-show)

    在Vue中使用v-if等条件实现条件的判断来实现对象的显示. 也可以采用 v-show条件来实现对象的显示.