利用UICollectionViewFlowLayout的隐式动画实现UICollectionView的layout的动画调整(外加放大指定cell效果)...

前几天在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手势的各种值都不会变,所以只能手动记录这个变化。。。

转载于:https://www.cnblogs.com/Phelthas/p/4537191.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值