自定义UICollectionView,主要会用到以下几个方法:

  1. - (void)prepareLayout; 第一次加载layout、刷新layout、以及- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;这个方法返回yes时,会调用。这是苹果官方的说明The collection view calls -prepareLayout once at its first layout as the first message to the layout instance. The collection view calls -prepareLayout again after layout is invalidated and before requerying the layout information. Subclasses should always call super if they override。实现该方法后应该调用[super prepareLayout]保证初始化正确。该方法用来准备一些布局所需要的信息。该方法和init方法相似,但该方法可能会被调用多次,所以一些不固定的计算(比如该计算和collectionView的尺寸相关),最好放在这里,以保证collectionView发生变化时,自定义CollectionView能做出正确的反应。
  2. - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; 该方法用来返回rect范围内的 cell supplementary 以及 decoration的布局属性layoutAttributes(这里保存着她们的尺寸,位置,indexPath等等),如果你的布局都在一个屏幕内 活着 没有复杂的计算,我觉得这里可以返回全部的属性数组,如果涉及到复杂计算,应该进行判断,返回区域内的属性数组,有时候为了方便直接返回了全部的属性数组,不影响布局但可能会影响性能(如果你的item一屏幕显示不完,那么这个方法会调用多次,当所有的item都加载完毕后,在滑动collectionView时不会调用该方法的)。
  3. - (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath; 该方法不是必须实现的,即便你实现了,我们对collectionView的任何操作,也不会导致系统主动调用该方法。该方法通常用来定制某个IndexPath的item的属性。当然我们也可以重写这个方法,将布局时相关的属性设置放在这里,在- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 或者 - (void)prepareLayout 中 需要创建用来返回给系统的属性数组 主动调用这个方法,并添加带可变数组中去返回给系统。当然我们也可以在 - (void)prepareLayout 中 通过[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] 获取 每个indexPath的attributes,在- (void)prepareLayout中设置所有item的属性。看需求以及个人喜欢。
  4. - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds; 用来刷新layout的,当我们返回yes的时候。如果我们的需求不需要实时的刷新layout,那么最好判断newBounds 和 我们的collectionView的bounds是否相同,不同时返回yes;(例如苹果官方的lineLayout,因为每次滑动都要放大item,所以这了就直接返回yes)。

以苹果官方的lineLayout为例,这个是对UICollectionViewFlowLayout的扩充,

-(id)init
{
self = [super init];
if (self) {
self.itemSize = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(, 0.0, , 0.0);//上下边距
self.minimumLineSpacing = 50.0;//行间距
}
return self;
}

这里初始化一些信息。

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}

因为滑动放大,故这里需要返回yes,实时刷新layout。

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray* array = [super layoutAttributesForElementsInRect:rect]; //可视rect
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size; //设置item的缩放
for (UICollectionViewLayoutAttributes* attributes in array) {
if (CGRectIntersectsRect(attributes.frame, rect)) {
CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;//item到中心点的距离
CGFloat normalizedDistance = distance / ACTIVE_DISTANCE;//距离除以有效距离得到标准化距离
//距离小于有效距离才生效
NSLog(@"%f",distance);
if (ABS(distance) < ACTIVE_DISTANCE) {
CGFloat zoom = + ZOOM_FACTOR*( - ABS(normalizedDistance));//缩放率范围1~1.3,与标准距离负相关
attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0);//x,y轴方向变换
//attributes.zIndex = 0;
}
}
} return array;
}

这里对item进行放大操作(因为该类是继承自UICollectionViewFlowLayout,苹果重写了该方法,所以调用super可以拿到当前rect范围内attributes,如果继承自UICollectionViewLayout,调用super是什么都拿不到的)。这里的思想就是:距离屏幕中心超过一定距离(假设200,自己设定)开始放大,CGFloat normalizedDistance = distance / ACTIVE_DISTANCE;item中心到屏幕中心点距离占200的比例,

CGFloat zoom = 1 + ZOOM_FACTOR*(1 - ABS(normalizedDistance));

这样便得到放大的倍数。

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
//proposedContentOffset是没有对齐到网格时本来应该停下的位置 //计算出实际中心位置
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0); //取当前屏幕中的UICollectionViewLayoutAttributes
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray* array = [super layoutAttributesForElementsInRect:targetRect]; //对当前屏幕中的UICollectionViewLayoutAttributes逐个与屏幕中心进行比较,找出最接近中心的一个
for (UICollectionViewLayoutAttributes* layoutAttributes in array) {
CGFloat itemHorizontalCenter = layoutAttributes.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment)) {
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
}
} //返回调整好的point
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 这个方法简单理解可以当作是用来设置collectionView的偏移量的,计算当前屏幕哪个item中心点距离屏幕中心点近,就将该item拉到中心去。

个人理解,不对的地方还请见谅。

关于自定义UICollectionViewLayout的一点个人理解<一>的更多相关文章

  1. 自定义UICollectionViewLayout并添加UIDynamic - scorpiozj(转)

    转载自:http://www.tuicool.com/articles/jM77Vf     自定义UICollectionViewLayout并添加UIDynamic UICollectionVie ...

  2. 自定义UICollectionViewLayout并添加UIDynamic

    大家也可以到这里查看. UICollectionView是iOS6引入的控件,而UIDynamicAnimator是iOS7上新添加的框架.本文主要涵盖3部分: 一是简单概括UICollectionV ...

  3. 自定义UICollectionViewLayout 实现瀑布流

    今天研究了一下自定义UICollectionViewLayout. 看了看官方文档,要自定义UICollectionViewLayout,需要创建一个UICollectionViewLayout的子类 ...

  4. 自定义UICollectionViewLayout 布局实现瀑布流

    自定义 UICollectionViewLayout 布局,实现瀑布流:UICollectionView和UICollectionViewCell 另行创建,这只是布局文件, 外界控制器只要遵守协议并 ...

  5. net core体系-web应用程序-4net core2.0大白话带你入门-8asp.net core 内置DI容器(DependencyInjection,控制翻转)的一点小理解

    asp.net core 内置DI容器的一点小理解   DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IO ...

  6. AngularJS』一点小小的理解

    『AngularJS』一点小小的理解   AngularJS 是一个前端的以Javascript为主的MVC框架.与AngularJS相类似的还有EmberJS. 随着时代在进步,各种各样的开发理念与 ...

  7. iOS 关于自定义UICollectionViewLayout实现复杂布局

    UICollectionView的简单介绍 UICollectionView的结构 Cells Supplementary Views 追加视图 (类似Header或者Footer) Decorati ...

  8. 自定义UICollectionViewLayout之CATransform3D

    1.自定义UICollectionViewLayout旋转效果 之前有自定义UICollectionViewLayout(适用于多个section),本文是一个对cell进行CATransform3D ...

  9. Layui的一点小理解(上)

    首先声明这是个人的一点理解,如有不对之处请指正,以下的例子有在官网上看到的,有的是自己写的.还是老规矩最后会附上官网的,如有不明白之处,请查看文档或留言. 既然说Layui,当然要简单的介绍以下什么是 ...

随机推荐

  1. 关于plist文件

    一.代码创建plist文件: NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomain ...

  2. exc_bad_access(code=1, address=0x789870)野指针错误

    原因: exc_bad_access(code=1, address=0x789870)野指针错误,主要的原因是,当某个对象被完全释放,也就是retainCount,引用计数为0后.再去通过该对象去调 ...

  3. javascript 概述及基础知识点(变量,常量,运算符,数据类型)

    JavaScript概述 1.1 什么是JavaScript: javaScript(简称js),是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言.同时也是一种广泛用于客户端Web开发的脚本语 ...

  4. uva11426 欧拉函数应用

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=121873#problem/F 题目大意:给你一个数n,让你输出(i=1-> ...

  5. 转载:s:if的用法

    转载网址:http://blog.csdn.net/menhuanxiyou/article/details/5709550 1:直接写表达式 <s:set name="china&q ...

  6. windows下配置lamp环境(1)---安装Apache服务器2.2.25

    window下lamp成为wamp; 安装wamp环境的第一步是安装Apache服务器.下面开始安装步骤图文并茂. 一.双击安装包点“next”进行下一步,然后同意协议(这张图没有截):

  7. CC2530定时器3的输入捕获中断

    CC2530定时器3的输入捕获中断 使用的是tim3的通道1的输入捕获P1_7口.//GPIO配置成复用功能,同时设置P1_7为输入.void irCaptureGpioInit(void){ P1S ...

  8. JDK Linux环境配置

    ① $sudo vi /etc/profile ② 在末尾行添加 #set java environment JAVA_HOME=/usr/local/jdk1.7.0 CLASSPATH=.:$JA ...

  9. juqery easy ui 实现二级菜单联动

    实现效果 代码: <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat= ...

  10. BZOJ 2298 problem a(区间DP)

    题意:一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话(可能有相同的分数) 思路:考虑最多有多少人说真,那么答案就是n-max. ai个人分数 ...