前几天在gitHub看到个不错的效果,就是DaiExpandCollectionView,效果如图:
 
所以赶紧下下来源码看看他怎么实现的,打开源码看了半天,发现他没写什么关于动画的代码啊。。。
经高人指点,才明白原来他是利用了UICollectionViewFlowLayout的隐式动画!
 
所谓隐式动画,就是系统自带的动画了,其实也不是什么高大上的东西,关键是我怎么就没想到可以这么用!
 
研究了半天人家的源码,基本了解了他实现的思路,然后发现他的这个库用起来比较不方便,需要继承他的collectionView,而且不能自定义cell大小,不能很好的适配各种尺寸的屏幕,
但这个库我确实很喜欢,所以就自己仿写了一个,就是LXMExpandLayout,顺便解决下上面发现的问题,地址在这里: https://github.com/Phelthas/LXMExpandLayout
效果如图:
                  
 
 
还是来说说思路和原理的问题
基本思路是:
     继承系统的UICollectionViewFlowLayout,利用UICollectionViewFlowLayout已有的各种属性和效果,对其做出适当的修改已达到自己想要的效果
 
具体来说就是:
1,重载  - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;方法,
用 [super layoutAttributesForElementsInRect:newRect]获取各个元素在 UICollectionViewFlowLayout中的layoutAttributes。
然后修改其属性
 
2,属性可不是随便改的,这个得给原作者点个赞,他想出来的这个规则,让这个属性的修改简单了好几倍。
这个规则就是:选中的item放大到这个item的旁边只能放得下一个没有放大的item!!!
这个规则的牛X之处在于:这样放大的item的右边,刚好可以放得下原来跟他同一行的剩下的item,进而需要修改属性的item就是原来跟需要放大的item同一行的item,剩下item,只需要简单的上下平移或者根本不用动!!!
 
3,知道了这个规则,就有了方向,可以大胆动手改了,选中的item用transform属性做平移和放大,其他的简单修改frame就可以了
这里怎么取出来和选中item同一行的其他item呢?
有个不错的方法,就是: self.sameRowItemArray = [super layoutAttributesForElementsInRect:CGRectMake(0, selectedAttributes.frame.origin.y, self.collectionViewWidth, self.itemHeight)];注意是super的方法,不是self~~
 
4,关键的时刻到了,怎么让collectionView执行隐形动画呢?
这个也是从原作者那里学到的,就是调用系统的 - (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion;方法。我把它封装成了一个collectionView的分类,方便配合我的LXMExpandLayout使用。
这个方法会使collectionView重新调用其layout去重新布局,而且是带动画的哦~~
 
5,直接调用performBatchUpdates方法的话,动画是线性的,那怎么样才能有弹簧的效果呢?
这里又从原作者那里学到一招:用一个UIView animation的block将则个performBatchUpdates包起来
这样就可以用UIView的animation动画代替performBatchUpdates的默认动画。利用iOS7自带的弹簧动画方法
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
效果杠杠的~~
 

6,发现个UICollectionView的系统bug,关于UICollectionViewFlowLayout的
UICollectionViewFlowLayout 的 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 方法返回的数组中有indexpath重复的对象,解决办法见:http://stackoverflow.com/questions/12927027/uicollectionview-flowlayout-not-wrapping-cells-correctly-ios/13389461#13389461  
 
其他还有一些细节需要注意的,代码里我已经写了注释了,这里就不在说了
具体这个库怎么使用,也已经写在gitHub上了,也就不罗嗦了。
有问题欢迎留言讨论~~
 
2015-06-27更新
添加拖动排序效果,参考的https://github.com/ra1028/RACollectionViewReorderableTripletLayout 的效果。
本来以为这个效果不会太难的,结果写了写简直蛋都碎了。。。写了好几天,比我想象的复杂好多,有好多需要注意的地方,估计还有很多隐藏的bug。。。慢慢发现慢慢修复吧。
值得记录一下的是:
1,利用手势的代理方法,让两个手势协同作用。
具体就是

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;方法和

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer方法。

加入适当的判断,就可以实现手势的协同。本例就是用这种方法让longPressGesture和panGesture协同作用实现拖动效果。

2,让scrollView自动滑动的方法
其实是利用一个定时器在需要的时候逐步设置scrollView的contentOffset,
需要注意的是:这时候pan手势的translation距离是不变的,但是view的位置却应该变。。。说起来都是泪啊!
因为设置了contentOffset,view的frame其实是应该变的,但是这时候手没动,所以pan手势的各种值都不会变,所以只能手动记录这个变化。。。

利用UICollectionViewFlowLayout的隐式动画实现UICollectionView的layout的动画调整(外加放大指定cell效果)的更多相关文章

  1. OC CollectionView和TableView自身高度的隐式递归计算,改变父试图布局

    CollectionView和TableView自身高度的隐式递归计算 1.前沿:我们一般会碰到这样的需求,一个tableview或者一个colletionview放在一个scrollview上边,而 ...

  2. Tips:取消UICollectionView的隐式动画

    http://www.cocoachina.com/ios/20151204/14211.html UICollectionView在reloadItems的时候,默认会附加一个隐式的fade动画,有 ...

  3. CALayer的隐式动画

    CALayer的使用 在我的理解中CALayer就是iOS中利用图层精简非交互式绘图.那么那些核心动画类.也就是变化图层的非交互式绘制规则而已.其中的本质就是将CALayer中的内容转化为map图.从 ...

  4. 非RootLayer的隐式动画

    非RootLayer都有隐式动画,默认0.25秒. // 1.开启 [CATransaction begin]; // 2.设置关闭 YES-关闭:NO-开启 [CATransaction setDi ...

  5. IOS第18天(3,CALayer隐式动画)

    ******隐式动画(手指拖拽Layer) #import "HMViewController.h" @interface HMViewController () @propert ...

  6. iOS:CALayer的隐式动画的详解

    CALayer的隐式动画属性: •每一个UIView内部都默认关联着一个CALayer,称这个Layer为Root Layer.所有的非Root Layer都存在着隐式动画,隐式动画的默认时长为1/4 ...

  7. IOS动画隐式,显式,翻页

    //  ViewController.m //  IOS动画0817 // //  Created by 张艳锋 on 15/8/17. //  Copyright (c) 2015年 张艳锋. Al ...

  8. iOS中的隐式动画

    隐式动画就是指  在 非 人为在代码中 定义动画  而系统却默认  自带   的动画  叫做隐式动画. 比如  改变 图层  的颜色  位置  和   透明度  的时候    都会  产生附带的渐变的 ...

  9. OC - 22.隐式动画

    简介 每个UI控件,默认自动创建一个图层(根图层),即每个UI控件对应于至少一个图层 每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)   ...

随机推荐

  1. mpi4py实践

    版权声明:本文为博主原创文章,未经博主允许不得转载. 1.概述 MPI(Message Passing Interface),消息传递接口,是一个标准化和轻便的能够运行在各种各样并行计算机上的消息传递 ...

  2. 操作系统页面置换算法(opt,lru,fifo,clock)实现

    选择调出页面的算法就称为页面置换算法.好的页面置换算法应有较低的页面更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出. 常见的置换算法有以下四种(以下来自操作系统课本). ...

  3. Android仿qq聊天记录长按删除功能效果

    最近项目在做IM即时通讯开发,在删除聊天列表的时候跟删除聊天详细信息的时候,产品经理想要跟ios一样,在当前选中行上方弹出一个删除窗口.于是先从网上找demo,找了一个发现是Dialog做的,我感觉没 ...

  4. jQuery.unique引发一个血案

    项目开发过程中,PM说系统只要在一个特定的浏览器中运行就好,但是在其他的浏览器中不能出现逻辑的错误,所以在开发过程中,前端和后台选择是Chrome浏览器,没有仔细测试Firefox和IE.但是昨天PM ...

  5. Objective-C中的内存管理

    在编程语言中是少不了对内存的管理的,内存对于计算机来说是宝贵的资源,所以对使用不到的资源进行回收是很有必要的.OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被 ...

  6. EntityFramework 如何查看执行的 SQL 代码?

    在 VS 调试的时候,如果我们项目中使用的是 EntityFramework,查看 SQL 执行代码就不像 ADO.NET 那样直观了,我们需要设置下,可以参考下: How can I log the ...

  7. iOS - 类扩展与分类的区别

    类扩展 (Class Extension也有人称为匿名分类) 作用: 能为某个类附加额外的属性,成员变量,方法声明 一般的类扩展写到.m文件中 一般的私有属性写到类扩展 使用格式: @interfac ...

  8. MongoDB的CRUD操作

    1. 前言 在上一篇文章中,我们介绍了MongoDB.现在,我们来看下如何在MongoDB中进行常规的CRUD操作.毕竟,作为一个存储系统,它的基本功能就是对数据进行增删改查操作. MongoDB中的 ...

  9. Struts2学习笔记--使用Response下载文件和Struts2的StreamResult文件下载

    使用Response下载文件,servlet中的文件下载是通过流来实现的   我在webRoot文件夹下新建了一个文件夹from,里边放了一张图片,这里就以下载这张图片为例:download.jsp很 ...

  10. 机器学习 1 linear regression 作业(二)

    这个线性回归的作业需要上传到https://inclass.kaggle.com/c/ml2016-pm2-5-prediction 上面,这是一个kaggle比赛的网站.第一次接触听说这个东西,恰好 ...