前几天在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. python调取C/C++的dll生成方法

    本文针对Windows平台下,python调取C/C++的dll文件. 1.如果使用C语言,代码如下,文件名为test.c. __declspec(dllexport) int sum(int a,i ...

  2. n个结点,不同形态的二叉树(数目+生成)

    题目链接: 不同的二叉查找树:http://www.lintcode.com/zh-cn/problem/unique-binary-search-trees/ 不同的二叉查找树 II:http:// ...

  3. 从零开始编写自己的C#框架(4)——文档编写说明

    在写本系列的过程中,了解得越多越不知道从哪里做为切入点来写,几乎每个知识点展开来说都可以写成一本书.而自己在写作与文档编写方面来说,还是一个初鸟级别,所以只能从大方面说说,在本框架开发所需的范围内来讲 ...

  4. JavaSE高级之集合类

    ​下面的内容是对java中的集合类进行的总结,过段时间会分享java的网路编程,多线程等内容,欢迎批评指正. 1.Java中的集合是用来存放对象的,即集合是对象的集合,对象是集合的元素,java AP ...

  5. 当Azure里的虚拟机网卡被禁用了之后……

    这样的想法来自于一个假设,如果网卡被禁用之后,用户该如何处理,Azure又该如何处理,对于设置在虚拟机中的禁用网卡选项是否还有存在的意义?通常情况下,点选了禁用网卡对于你和虚拟机来说就一下之抓瞎了,瞬 ...

  6. java多线程--定时器Timer的使用

    定时的功能我们在手机上见得比较多,比如定时清理垃圾,闹钟,等等.定时功能在java中主要使用的就是Timer对象,他在内部使用的就是多线程的技术. Time类主要负责完成定时计划任务的功能,就是在指定 ...

  7. C#图片存入数据库及其读出显示

    <1>将图片转换成二进制插入数据库 FileStream fs = new FileStream("D:\\Add.ico",FileMode.Open); byte[ ...

  8. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  9. Windows下Thumbnail的开发总结

    一.引言 Windows Thumbnail Handler是Windows平台下用来为关联的文件类型提供内容预览图的一套COM接口.通过实现Thumbnail相关的COM接口,就可以为为自定义的文件 ...

  10. MVC学习系列11---验证系列之客户端验证

    前面学习了,服务端验证,这篇文章中,我们接着学习客户端验证,客户端的验证,使用Jquery和Jquery插件来实现[jquery.validate.min.js and jquery.validate ...