如何实现iOS图书动画-第2部分(上)
- 原文链接 : How to Create an iOS Book Open Animation: Part 2
- 原文作者 : Vincent Ngo
- 译文出自 : 开发技术前线 www.devtf.cn
- 译者 : kmyhy
欢迎回到iOS图书动画系列教程!在第一部分,我们学习了如何创建两个自定义的collection view layout并在图书书页中使用了阴影图层以使我们的App显得更加立体和真实。
在这一部分,我们将学习如何创建自定义的转场动画并通过捏放手势来打开一本书。
注意:感谢Attila Hegedüs创建了本教程的示例程序。
开始
本教程以前一部分的内容为基础。如果你还没有看过第一部分,或者想从一个新项目开始,你可以在这里下载上一部分教程中的完整示例程序。
在Xcode中打开项目。现在,你可以选择一本书进行阅读,并从右边滑动进行翻页。这时的转场动画使用的是UINavigationController自带的动画效果。通过本教程的学习,我们将自定义这个动画效果,如下图所示:
这个动画会在“打开书”和“合起书”两个状态之间一一种更加自然的方式平滑过渡,这将更能获得用户的欢心。让我们马上开始吧!
创建自定义的导航控制器
要创建自定义的push动画和pop动画,我们必须创建自定义导航控制器并实现UINavigationControllerDelegate协议。
在App文件夹上右击(或ctrl+左键)并点击New File。选择iOS\Source\Cocoa Touch Class模板并将类名设置为CustomNavigationController。让它继承自UINavigationController并将语言设置为Swift。点击Next,Create。
打开CustomNavigationController.swift,编辑其内容为:
import UIKitclass CustomNavigationController: UINavigationController, UINavigationControllerDelegate {override func viewDidLoad() {super.viewDidLoad()//1delegate = self}//2func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {if operation == .Push {return nil}if operation == .Pop {return nil}return nil}
}
上述代码分别解释如下:
- 在 viewDidLoad 方法中,设置CustomNavigationController的delegate属性为它自己。
- navigationController(_:animationControllerForOperation:fromViewController:toViewController:) 方法属于UINavigationControllerDelegate协议。这个方法在两个View Controller之间发生push或pop导航时调用。你可以在这个方法中分别针对push导航和pop导航返回各自的Transition对象。目前我们都返回了nil,这表明我们将使用UINavigationController内置的标准Transition。稍后我们将替换为自己的Transition对象。
现在我们拥有了自己的Navigation Controller类,接下来在故事板中将默认的UINavigationController替换为我们的CustomNavigationController。
打开Main.storyboard,在故事板编辑器左侧的对象窗口中选择Navigation Controller对象,打开Identity窗口,在Custom Class下,将Class由UINavigationController修改为CustomNavigationController,如下图所示:
编译运行,什么变化都没有发生。这是因为在委托方法中我们仍然返回了nil,因此使用的仍然是UINavigationController内置的标准Transition。
创建自定义导航动画
最有趣的部分来了——创建我们的自定义Transition对象!:]
要自定义Transition类,我们必须实现UIViewControllerAnimatedTransitioning协议,最主要的是这几个方法:
- transitionDuration: 必须实现。这个方法返回一个动画时长,使两个动画的播放时间相同(或不同)。
- animateTransition: 必须实现。这个方法负责提供参与动画的两个控制器:一个to控制器,一个from控制器。Transiton的大部分工作在这个方法中完成。
- animationEnded: 可选的方法。这个方法主要是用来通知你什么时候动画完成了。我们可以在这个方法中进行必要的清理动作。
创建自定义Transition类
在App文件夹上右击(或ctrl+左键),然后点击New File。选择iOS\Source\Coca Touch Class 模板,将类名设置为BookOpeningTransition,继承NSObject,语言Swift。然后点击Next,Create。
打开BookOpeningTransition.swift,编辑代码如下:
import UIKit//1
class BookOpeningTransition: NSObject, UIViewControllerAnimatedTransitioning {// MARK: Stored propertiesvar transforms = [UICollectionViewCell: CATransform3D]() //2var toViewBackgroundColor: UIColor? //3var isPush = true //4//5// MARK: UIViewControllerAnimatedTransitioningfunc transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {return 1}func animateTransition(transitionContext: UIViewControllerContextTransitioning) {}
}
以上代码对应注释中的编号,分别解释如下:
- 声明 BookOpeningTransition 类实现UIViewControllerAnimatedTransitioning 协议。
- 声明一个 transforms 字典,键存储UICollectionViewCell,值则存储对应的CATransiform3D。这个字典保存在书打开后所有cell的翻页动画。
- 指定to视图控制器的背景色,它将让淡出淡入动画看起来更加清楚。
- 布尔值isPush 用于标识当前动画是Push动画还是Pop动画。
- 增加必须实现的 UIViewControllerAnimatedTransitioning 协议方法,以使编译错误不再出现,稍后我们会实现这些方法。
定义好需要的变量,接下来就是实现协议方法。
首先是transitionDuration(_:)方法:
if isPush {return 1
} else {return 1
}
transitionDuration(_:)方法返回了动画播放时长。这里,无论是Push动画还是Pop动画我们都设置为1秒。通过这个方法我们可以很方便地改变Push动画或Pop动画的时长。
然后,是第二个协议方法——animateTransition——这是最核心的部分!:]我们将这个方法分成两部分来介绍:
- 实现一个助手方法,用于创建Push动画所需的Transition对象。
- 实现一个助手方法,用于创建Pop动画所需的Transition对象。
创建Push动画
回想你在生活中打开一本书的样子:
虽然看起来复杂,但我们只需要考虑两个状态,同时让UIView的animateWithDuration方法根据这两个状态进行不同的处理:
- 状态1,书处于合起状态。
- 状态2,书处于打开状态;这就是我们在第一部分教程中实现的部分。
首先,在实现animateTransition(:_)协议方法之前,我们来实现几个助手方法。
仍然在BookOpeningTransition.swift中,编写如下方法:
// MARK: Helper Methods
func makePerspectiveTransform() -> CATransform3D {var transform = CATransform3DIdentitytransform.m34 = 1.0 / -2000return transform
}
这个方法返回了一个Transform对象,并在z轴上增加了一点立体感。在播放动画时,我们将用到这个方法。
状态 1 - 合起书
在makePerspectiveTransform方法后实现如下方法:
func closePageCell(cell : BookPageCell) {
// 1
var transform = self.makePerspectiveTransform()
// 2
if cell.layer.anchorPoint.x == 0 {
// 3
transform = CATransform3DRotate(transform, CGFloat(0), 0, 1, 0)
// 4
transform = CATransform3DTranslate(transform, -0.7 * cell.layer.bounds.width / 2, 0, 0)
// 5
transform = CATransform3DScale(transform, 0.7, 0.7, 1)
}
// 6
else {
// 7
transform = CATransform3DRotate(transform, CGFloat(-M_PI), 0, 1, 0)
// 8
transform = CATransform3DTranslate(transform, 0.7 * cell.layer.bounds.width / 2, 0, 0)
// 9
transform = CATransform3DScale(transform, 0.7, 0.7, 1)
}
//10
cell.layer.transform = transform
}
回想一下BookViewController,它是一个CollectionView,代表了书中的一页。我们将每一页和书脊对齐,以y轴为心进行旋转实现翻页效果。首先,书是合起(关闭)的。这个方法将每个cell(即书页)放平并置于封面的下面。
这是动画运行效果:
以上代码解释如下:
- 用前面创建的助手方法,生成一个Transform对象。
- 判断cell是否是右侧页。
- 如果是,设置其角度为0,即放置为水平。
- 将它移动到封面下方并居中对齐。
- 将它缩放为70%。还记得我们前面将封面也缩放为70%吗?这里是同样的意思。
- 如果cell不是右侧页,则就是左侧页。
- 设置左侧页的角度为180度。要将它水平放置,我们需要将它翻到书脊的右边。
- 将它放到封面下方并居中对齐。
- 缩放70%。
- 最后,赋给cell的transform属性。
在上面的方法后添加如下方法:
func setStartPositionForPush(fromVC: BooksViewController, toVC: BookViewController) {// 1toViewBackgroundColor = fromVC.collectionView?.backgroundColortoVC.collectionView?.backgroundColor = nil//2fromVC.selectedCell()?.alpha = 0//3for cell in toVC.collectionView!.visibleCells() as! [BookPageCell] {//4transforms[cell] = cell.layer.transform//5closePageCell(cell)cell.updateShadowLayer()//6if let indexPath = toVC.collectionView?.indexPathForCell(cell) {if indexPath.row == 0 {cell.shadowLayer.opacity = 0}}}
}
setStartPositionForPush(_:toVC:)方法创建状态1的Transition。这个动画涉及到两个ViewController:
fromVC,类型为BooksViewController,用于滚动浏览图书列表。
toVC,BookViewController类型,让你可以翻阅选定的书。
以上代码解释如下:
- 保存BooksViewController的Cellection View的背景色,然后设置BookViewController的Collection View的背景色为nil。
- 隐藏封面。现在toVC将负责处理封面图片的显示。
- 遍历书中所有书页。
- 保存每一页的当前Transform到transforms字典。
- 由于书一开始是合起的,我们将该页转换为合起状态,然后更新阴影图层。
- 最后,忽略封面图片的阴影。
如何实现iOS图书动画-第2部分(上)相关推荐
- 如何实现iOS图书动画:第1部分(上)
如何实现iOS图书动画:第1部分 原文链接 : How to Create an iOS Book Open Animation: Part 1 原文作者 : Vincent Ngo 译文出自 : 开 ...
- 如何实现iOS图书动画-第2部分(下)
原文链接 : How to Create an iOS Book Open Animation: Part 2 原文作者 : Vincent Ngo 译文出自 : 开发技术前线 www.devtf.c ...
- 如何实现iOS图书动画:第1部分(下)
原文链接 : How to Create an iOS Book Open Animation: Part 1 原文作者 : Vincent Ngo 译文出自 : 开发技术前线 www.devtf.c ...
- iOS常用动画 类封装
//这是一个很好的动画封装类 很容易明白很详细 和大家分享 // CoreAnimationEffect.h // CoreAnimationEffect // // Created by Vince ...
- [iOS]过渡动画之高级模仿 airbnb
注意:我为过渡动画写了两篇文章: 第一篇:[iOS]过渡动画之简单模仿系统,主要分析系统简单的动画实现原理,以及讲解坐标系.绝对坐标系.相对坐标系,坐标系转换等知识,为第二篇储备理论基础.最后实现 M ...
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
- 转-- iOS 30多个iOS常用动画,带详细注释
// // CoreAnimationEffect.h // CoreAnimationEffect // // Created by VincentXue on 13-1-19. // Copyri ...
- iOS 核心动画 Core Animation浅谈
代码地址如下: http://www.demodashi.com/demo/11603.html 前记 关于实现一个iOS动画,如果简单的,我们可以直接调用UIView的代码块来实现,虽然使用UIVi ...
- iOS核心动画高级技术(九) 图层时间
The biggest difference between time and space is that you can't reuse time. 时间和空间最大的区别在于,时间不能被复用 -- ...
最新文章
- 计算机维护系统Win8PE,u启动windows8PE工具箱
- es springboot 不设置id_es(elasticsearch)整合SpringCloud(SpringBoot)搭建教程详解
- R语言ggplot2可视化为长文本轴标签自动换行美化可视化结构实战:Wrap long text axis labels
- 「每周论文推荐」 初入深度学习CV领域必读的几篇文章
- 2019中国大学生程序设计竞赛(CCPC)-网络选拔赛-第七题Shuffle Card
- Android事件处理--读书笔记
- 今日收到的智商税:远红外
- 女生国庆和程序员相亲,就因为对方一个问题!女生:还要继续吗?
- VTK:可视化之MovableAxes
- 服务器php 启动命令_禁止php运行服务器命令行函数的安全配置
- python爬虫源代码_零基础自学爬虫(5)B站有哪些爬虫的视频学习资源-附Python源代码...
- mysql5批处理_转关于mysql5.5 的批处理讨论(转载)
- 在SOLIDWORKS Electrical中,如何创建电气原理图符号库?
- html5 扩展 cs6,Dreamweaver CS6提高了HTML5工具的效率
- 【C++】2048游戏系列---优化模块第一稿【加载图片】
- deepin系统安装nginx
- java 大臣的旅费_蓝桥杯 大臣的旅费(Java dfs)
- 为什么大家都在用 PDF? PDF 文档怎么修改?
- 以太坊:快速入门 Truffle
- ultraedit 注册激活
热门文章
- 金融成AI最佳应用场景,“智能金融”时代真的来了么?
- 【Web】HTML+CSS(No.55)实现小米官网首页静态效果
- 一个数码管显示0-F
- 062是c语言常量吗,C语言ch062二维数组.pptx
- Hotel booking demand 酒店预订需求分析
- 【HTML】标签简单融合运用
- SQL存储过程总结 - sql server 2012数据库基础-存储过程及应用-实验报告
- Scrapy爬取豆瓣图书详情存入CSV并导入MySQL
- 【unity】战棋项目总结随机贴图,鼠标悬置放大
- Python获取国内股票数据