iOS过场动画调研笔记
前言
因项目须要,近期一段时间都在调研iOS的过场动画。对于我来说这是一个之前没有太涉及的领域,所以有必要把调研的过程和自己的一些理解纪录下来
为什么要自己定义过场动画?
假设大家有关注Material Design和近期一些知名App(如快的、一号专车等)的界面设计和交互的变化,就会发现一种新的趋势:平滑的页面过渡。目的旨在于让用户尽量少地感觉到页面之间生硬的切换,从而使App的体验更加流畅。而iOS原生的两种经常使用过场:Push/Pop和Present,和眼下流行的趋势显然是不太符合的。所以自己定义过场动画的意义就体现出来了。
Transition-iOS的自己定义过场
简单介绍
由于之前有博客对自己定义过场做了很详细的介绍,我就不赘述了,详细參照这里 iOS7之定制View Controller切换效果 (PS:感谢作者)。作者的demo我也有下载看过。他是为每一个过场动画封装了单独的类,然后在UIViewController中实现过场切换的代理,在代理中返回对应的动画效果。对于为过场动画封装单独的类这点我是很赞同的,可是在UIViewController中实现过场切换的代理这一点我认为不是特别理想,所以后来我的实现做了改动,终于的效果是在UIViewController中仅仅须要调用一个接口。就能够实现自己定义过场的效果。
我的设计
分析
首先,我封装了一个单例模式MBTransition基类,使用单例模式的原因有两个:
- 在一个App中,同一时候存在的过场仅仅会有一个。
- 实现成单例之后过场对象就不须要依赖于某个UIViewController。
然后.m文件里为这个类实现过场动画的几个代理
#pragma mark UINavigationControllerDelegate methods
// Push/Pop时自己定义过场的代理
// 參数:
// navigationController:导航
// operation:导航的操作:Push/Pop/None,能够用来控制在哪种导航的操作下使用自己定义过场
// fromVC:运行Push操作的UIViewController
// toVC:被Push的UIViewController
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC {
return self; //返回self表示代理由类本身实现
}
// Present时自己定义过场的代理
// 參数:
// presented:被Present的UIViewController
// presenting:正在运行Present的UIViewController
// source:发起Present的UIViewController(PS:正在运行Present和发起Present的UIViewController是有差别的,
// 假设source是某个UINavigationController下的一个UIViewController,
// 那么presenting就是这个UINavigationController,假设source不是在相似UINavigationController或者
// UITabbarController这种控件内。那么presenting就是source本身)
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
return self;
}
// Dismiss时自己定义过场的代理
// 參数:
// dismissed:被Dismiss掉的UIViewController
-(id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return self;
}
#pragma mark - UIViewControllerContextTransitioning
// 实现详细自己定义过场动画效果的代理,这个代理也是实现动画效果的核心
// 參数:
// transitionContext:过场时的上下文信息
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
}
// 过场动画时间的代理
// 參数:
// transitionContext:过场时的上下文信息
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return self.duration;
}
通过上面几个代理我们能够知道:Push/Pop和Present时过场动画的代理是不一样的,所以我建立了一个过场类型的枚举,用来控制自己定义过场在哪种交互下可用:
typedef enum TransitionType{
TransitionTypePush, // Push/Pop过场
TransitionTypePresent // Present过场
}TransitionType;
然后在- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext代理中我们返回了self.duration,所以我们须要在.h文件里加入一个变量来保存过场动画持续的时间:
@property (nonatomic, assign) NSTimeInterval duration;
接下来我们分析一下 (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext 代理中我们做的一些事情:
通过
transitionContext获取到过场时切换的两个UIViewController// 这里的 fromVC 和 toVC 代表的是过场是由 fromVC 切换到 toVC 的。
// 比方从A界面Push到B界面时,这里的fromVC是A界面,toVC是B界面,而当B界面被Pop到A界面时,
// 这里的fromVC就是B界面。toVC就是A界面
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];通过
transitionContext获取到运行切换的UIView// 全部的切换动画都是基于container来实现的
UIView *container = [transitionContext containerView];通过
transitionContext获取到过场的持续时间NSTimeInterval duration = [self transitionDuration:transitionContext];最后通过
transitionContext获取到过场时切换的 fromVC 和 toVC 和Push/Present时保存的 fromVC 和 toVC 进行比較就能够知道眼下运行的是Push/Present还是Pop/Dismiss,从而能够为Push/Present和Pop/Dismiss定制不同的动画效果。- (BOOL)isReversed:(UIViewController *)fromVC ToVC:(UIViewController *)toVC
{
return !([self.fromVC class] == [fromVC class] && [self.toVC class] == [toVC class]);
}所以我们须要在.h文件里加入两个成员变量来保存Push/Present时的 fromVC 和 toVC :
@property (nonatomic, weak) UIViewController *fromVC;
@property (nonatomic, weak) UIViewController *toVC;接下来就是详细的过场动画部分了。事实上就是结合fromVC的view、toVC的view和container做一些动画效果,由于跟做普通的动画没有什么差别,所以这个部分我就不详细描写叙述了。
最后是提供给外部调用的接口,内容例如以下:
- (void)setTransitionWithFromViewController:(UIViewController *)fromVC
ToViewController:(UIViewController *)toVC
TransitionType:(TransitionType)type
Duration:(NSTimeInterval)duration{
self.fromVC = fromVC;
self.toVC = toVC;
self.duration = duration;
if (type == TransitionTypePush) {
self.fromVC.navigationController.delegate = self;
}else if (type == TransitionTypePresent){
self.fromVC.transitioningDelegate = self;
self.toVC.transitioningDelegate = self;
}
}
上面代码片段所做的事情就是对一些參数进行保存,然后依据 TransitionType(这就是之前那个枚举类型) 来设置对应的代理。
特点
- 假设要实现其它自己定义过场,仅仅须要继承MBTransition,然后重写
(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext代理就可以。 - 使用者仅仅需调用一个接口就可以实现自己定义过场,减少了代码耦合。
交互式的切换动画
交互式动画主要是指动画能够跟用户的手势连动,这个部分我眼下还没有研究…后面有机会再补上
碰到的一些坑
- 当UIViewController是UITabbarController或者UINavigationController的一个childViewController时。通过
[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]和[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]拿到的UIViewController事实上是UITabbarController或者UINavigationController。所以在调用接口时,要注意传入的 fromVC 和 toVC 事实上是这个UIViewController的UITabbarController或者UINavigationController,假设不这样做,isReserved方法的推断就会发生异常。 假设採用Push/Pop的方式。当fromVC属于UITabbarController的一个childViewController,且在 toVC 上不能显示UITabbarController的UITabBar时。UITabbarController的UITabBar会造成很大的麻烦:
- 假设使用设置hidesBottomBarWhenPushed为true的方式,那么UITabBar的动画不能定制。仅仅能是默认的从右到左和从左到右。
- 假设使用自己定义的方式显示和隐藏UITabBar,由于AutoLayout的原因。后期问题会很多其它(PS:也可能是我对这种方法的研究还不够透彻)…
所以在这种情况下建议使用Present的方式切换到新的界面,当然假设大家有好的解决方法也希望能分享给我,谢谢!
后话
假设须要详细的代码,能够通过我的微博联系我画渣程序员mmoaay
iOS过场动画调研笔记的更多相关文章
- iOS动画技术笔记
概述 在IOS开发中,实现动画操作的地方有很多,典型的是在视图控制器的segue操作时.在同一个视图控制器类中,加载切换不同的视图时,也需要动画效果,还有一些视图对象有动画效果会更好. 插一句,在IO ...
- Implicit Animations 默认动画 读书笔记
Implicit Animations 默认动画 读书笔记 Do what I mean, not what I say. Edna Krabappel, The Simpsons Part I ...
- iOS燃烧动画、3D视图框架、天气动画、立体相册、微信朋友圈小视频等源码
iOS精选源码 iOS天气动画,包括太阳,云,雨,雷暴,雪动画. 较为美观的多级展开列表 3D立体相册,可以旋转的立方体 一个仪表盘Demo YGDashboardView 一个基于UIScrollV ...
- Android动画学习笔记-Android Animation
Android动画学习笔记-Android Animation 3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
- IOS 核心动画之CAKeyframeAnimation - iBaby
- IOS 核心动画之CAKeyframeAnimation - 简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation ...
- Swift 动画学习笔记
视频地址: http://www.swiftv.cn/course/i275v5lz 1,动画属性 position(位置),opacity(透明度,0 全透明,1 不透明),Scale(尺寸),Co ...
- iOS各种动画效果
ios各种动画效果 最普通动画: //开始动画 [UIView beginAnimations:nil context:nil]; //设定动画持续时间 [UIView setAnimationDu ...
- IOS之动画
IOS之动画 15.1 动画介绍 15.2 Core Animation基础 15.3 隐式动画 15.4 显式动画 15.5 关键帧显式动画 15.6 UIView级别动画 15.1 动画介绍 ...
随机推荐
- Git提交.net项目的小问题
今天早上写了点关于asp.net core授权的东西,输入git add .的时候出现的报错 $ git add .error: open(".vs/DOTNETAuthorization/ ...
- 【习题 7-8 UVA-12107】Digit Puzzle
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 枚举最大层数.(也即改变的数字个数 然后枚举第一个改哪个数字,第二个改哪个数字.. 一定要注意字典序问题. 每次优先 ...
- Native开发与JNI机制详解
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 文/李森 博主导读:博主不是代码大师,研究什么都很深,Java除外,所以无论什么问题,方案可以提供, ...
- Vijos——T 1164曹冲养猪
https://vijos.org/p/1164 描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数 ...
- 使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定、捕获所有异常、非常适合从头开始,但大公司已经有现成的C++框架、所以不会使用)
使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?和C Socket服务器比起来有什么优劣?可行性怎么样? 从2013年起,经朋友推荐开始用Golang编写游戏登陆服务器, 配合C++做第三方 ...
- js进阶 14-7 jquery的ajax部分为什么需要对表单进行序列化
js进阶 14-7 jquery的ajax部分为什么需要对表单进行序列化 一.总结 一句话总结:如果用ajax传递表单的数据,如果不进行表单的序列化,要一个参数一个参数的写,太麻烦,序列化的话,一句代 ...
- TeamViewer的下载、安装和使用(windows7、CentOS6.5和Ubuntu14.04(64bit))(图文详解)
不多说,直接上干货! TeamViewr是远程支持.远程访问.在线协作和会议软件. 分为从windows7.CentOS6.5和Ubuntu14.04(64bit) 系统来详解下载.安装和初步使用! ...
- C#集合类:动态数组、队列、栈、哈希表、字典
1.动态数组:ArrayList 主要方法:Add.AddRange.RemoveAt.Remove 2.队列:Queue 主要方法:Enqueue入队列.Dequeue出队列.Peek返回Queue ...
- 洛谷 P1206 [USACO1.2]回文平方数 Palindromic Squares
P1206 [USACO1.2]回文平方数 Palindromic Squares 题目描述 回文数是指从左向右念和从右向左念都一样的数.如12321就是一个典型的回文数. 给定一个进制B(2< ...
- Stable Matching (Gale Sharpley Algorithm)
稳定婚配问题:n个男生n个女生.当中每一个人都有自己心仪的列表. 问怎样达成稳定的匹配(比方, b想B求婚,可是B已有的对象的优先级高于b,此时b的魅力不足以拆散B所处的那一对,即达到稳定状态.) ( ...