当UICollectionView遇上动画

UICollectionView的简单介绍

在iOS6发布前,开发人员都习惯用UITableView来展示所有类型的数据集合。虽然苹果公司在照片应用中使用过很长一段时间类似UICollectionView视图的UI,但第三方开发人员无法使用它。当时我们可以利用第三方框架(如three20)来做类似的功能。在iOS6苹果引入了一个新的控制器UICollectionViewController。提供了一个更加优雅的方法,把各种类型的数据显示在视图中。
现在, 在各种类型的APP中,UICollectionView的身影随处可见,不管在什么应用,总有UICollectionView的应用场景,而苹果也在iOS10中对UICollectionView做了更好的优化。本文主要是展示UICollectionView的常用动画和装逼动画,也会在本文对所有的动画进行详细的讲解。先看效果

效果1:

效果2 : 圆形放大

效果3 :

效果4:

开车前

大家看标题就能知道,前两个效果需要掌握自定义转场的相关姿势,如果有的同学不太了解,简书上有很多相关的文章.也可以参考下喵神的的博客->WWDC 2013 Session笔记 – iOS7中的ViewController切换.或者先看下相册效果实现的思路.

效果1实现思路

先说下长按拖拽单元格的实现,这个是最简单的,只需要实现UICollectionViewcollectionView?.moveItemAtIndexPath(NSIndexPath, toIndexPath: NSIndexPath)所以我们要先记录移动之前的indexPath记录为lastPath,根据手指的位置获取目标位置的indexPath记录为curPath,移动完成后记录lastPath = curPath就能实现拖拽单元格的动画效果。最后一步就是修改数据源了,刚开始做的时候我傻逼的在手势结束的修改数据源,这是不行的.因为在移动的时候单元格已经变化太多了,所以一定要在移动的状态修改数据源.

添加长按手势

核心代码

图片浏览器思路

思考
  • 点击cellModal出来的View是什么类型的?
  • 怎么让Modal的View显示cell里面的图片?
  • 怎么才能知道点击cellframe?
  • 怎么才能知道dismiss之后cellframe?

第一个问题的答案已经很明显了,肯定是UICollectionView,我们可以在modalVC用属性记录点击cell的indexPath,通过调用collectionView.scrollToItemAtIndexPath(NSIndexPath, atScrollPosition: UICollectionViewScrollPosition, animated: Bool),值得注意的是animated要传false,你懂得.
关于第三个问题,我们可以直接计算让modalVC的一个属性来接收.我们还可以通过另外一种优雅的方式(代理)来获取。
第四个问题,因为最终的indexPath只有modalVC才能知道,所以也能通过代理来获得dismiss之后cellframe.

协议和代理方法的定义

代理方法的实现

Presented部分

dismiss部分

动画核心代码

效果2实现思路

首先,要实现这个效果,要用到CALayermask属性,mask属性很容易理解,就是一个遮罩,这个动画就是用一个圆形的遮罩不断地放大。遮罩也是一个CALayer,但是CALayer并不能完成这样的效果,这个时候我们可以使用它的子类CAShapeLayer.该子类有个属性path,可以画出各种图形.
当点击某个cell的时候,就以它的中心点为圆心,接下来就是求圆形半径的问题了,求半径的思路有两种。

半径思路一

2170968-9c185d8fd7a4fcfd

注意:如果点击的是cell0,就不能以cell0的中心点连线到左下角了,因为用这样的半径画出来的圆是不能覆盖整个屏幕的,所以要连线到右下角才可以.因此得出x = cell.center.x或者 x = collectionView.width - cell.center.x。我们可以用数学函数max()来获得x值而不是通过复杂的条件语句

半径思路二

以屏幕中心点为圆心,根据屏幕widthheight求出来的半径来画一个圆,这样也可以实现.我在dismiss的时候就是用得这个方法。下面上代码

presented部分核心代码

dismiss部分核心代码

效果3动画思路

首先,介绍UICollectionViewLayout的几个方法,在这个案例中,我们需要重写这几个方法。

这个方法返回指定rectcell的布局属性(layoutAttributes)数组。默认返回nil,这个方法是只要拖动UICollectionView的时候就会调用
我们来看一下UICollectionViewLayoutAttributes的头文件有哪些属性

可以看到这个对象可以拿到cellframecentersizetransform3D等属性,而且都是readWrite,我们可以利用这个方法,来实时改变celltransform,达到我们想要的效果

思路:看效果3的gif可以发现,当cellcollectionView得中心点越近,尺寸就越大,当它们的中心点重合的时候,cell的尺寸就是最大。所以要算出cell的中心点和collectionView中心点的距离。

2170968-1c4ff516dac7debb

图画得不好,大家凑合看看吧。计算完距离,下一步就是要计算缩放比例了,这一步大家可以按照自己的需求来计算.我的方案是:当cell的中心点离collectionView的中心点是collectionView.width * 0.5时,就缩放3/4

核心代码

进一步思考

能不能在松手的时候计算cell的缩放比例,让比较大的cell的中心点和collectionView的中心点对齐?可以使用这个方法

当我们松手的时候,就会调用这个方法,默认的返回值是proposedContentOffset

核心代码

效果4思路

和效果3完全一样。

额外补充

在效果3中,用到了CAShapeLayermask.如果还对这两个不太明白的话,推荐一些博客给大家能够更加清楚的了解
放肆的使用UIBezierPath和CAShapeLayer画各种图形
关于使用CALayer中mask的一些技巧

用好mask能做出比较酷炫的动画,比如

或者iPhone锁屏的文字效果

具体可以看下这边文章->Facebook Shimmer 实现原理

还有iOS10 UICollectionView的新特性
WWDC2016 Session笔记 – iOS 10 UICollectionView新特性

1 3 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部