详解 iOS 系统中的视图动画
动画为用户界面的状态转换提供了流畅的可视化效果,在iOS中大量使用了动画效果,包括改变视图位置、大小、从可视化树中删除视图,隐藏视图等。你可以考虑用动画效果给用户提供反馈或者用来实现有趣的特效。
在iOS系统中,CoreAnimation提供了内置的动画支持,创建动画不需要任何绘图的代码,你要做的只是激发指定的动画,接下来就交给CoreAnimation来渲染,总之,复杂的动画只需要几行代码就可以了。
哪些属性可以添加动画效果
根据iOS视图编程指南中说明,UIView内置支持为下列属性添加动画效果:
- Frame可以改变视图相对于上一级视图的位置和大小。(如果视图已经经过了缩放、旋转、平移之类的变换,则需要修改Center和Bounds属性)
- Bounds改变视图大小。
- Center改变视图相对于上级视图的位置。
- Transform相对于中心点进行视图缩放、旋转和平移,这个属性只能进行二维转换。(如果要进行三维转换,则必须用CoreAnimation操作视图的Layer属性。)
- Alpha改变视图的透明度。
- BackgroundColor修改视图的背景色。
- ContentStretch改变视图内容在视图的可用空间内的拉伸方式。
为视图的属性变化添加动画
为了给属性的变化添加动画效果,需要把修改这些属性的代码放到指定的动画代码段(animationblock)中。只有在动画代码段中修改支持动画的属性,才能添加动画效果。
使用Begin/Commit方法做动画
在iOS3.0以及之前的系统中,必须使用UIView的类方法beginAnimations:context:和commitAnimations来定义动画代码段,在begin和commit之间的代码会在特殊的动画线程中运行,因此不会阻塞主线程,比如说要切换两个视图,代码应该是这样子的:
[UIViewbeginAnimations:@"ToggleViews"context:nil]; [UIViewsetAnimationDuration:1.0]; //Maketheanimatablechanges. firstView.alpha=0.0; secondView.alpha=1.0; //Committhechangesandperformtheanimation. [UIViewcommitAnimations];
在Xamarin.iOS(MonoTouch)平台下,begin/end方法对应的绑定为:
- publicstaticvoidBeginAnimations(stringanimation)
- publicstaticvoidBeginAnimations(stringanimationID,IntPtrcontext)
- publicstaticvoidCommitAnimations()
上面的切换视图的C#版本代码为:
UIView.BeginAnimations("ToggleViews"); UIView.SetAnimationDuration(1.0) this.FirstView.Alpha=0.0; this.SecondView.Alpha=1.0; UIView.CommitAnidations();
在Begin/Commit函数之间,可以通过下面的方法设置动画的参数和选项:
- setAnimationStartDate:
- setAnimationDelay:
- setAnimationDuration:
- setAnimationCurve:
- setAnimationRepeatCount:
- setAnimationRepeatAutoreverses:
- setAnimationDelegate:
- setAnimationWillStartSelector:
- setAnimationDidStopSelector:
- setAnimationBeginsFromCurrentState:
注意:如果不是为了支持很旧的设备,则推荐使用下面的lambda(blockbasedmethod)来实现动画效果,虽然begin/commit还能够使用,按照官方的说法,对新系统来说是不推荐的了。
使用lambda(blockbasedmethod)做动画
在iOS4.0以后,引入了代码块(codeblock)的概念,可以使用代码块来初始化动画,这也是在iOS4.0之后苹果推荐的做法,iOSSDK提供的API如下:
- animateWithDuration:animations:
- animateWithDuration:animations:completion:
- animateWithDuration:delay:options:animations:completion:
而在Xamarin.iOS(MonoTouch)平台下,这些方法被绑定为下列方法:
- publicstaticvoidAnimate(doubleduration,NSActionanimation)
- publicstaticvoidAnimate(doubleduration,NSActionanimation,NSActioncompletion)
- publicstaticvoidAnimate(doubleduration,doubledelay,UIViewAnimationOptionsoptions,NSActionanimation,NSActioncompletion)
还是切换视图的动画,如果用objective-c的代码块来实现,则应该是这样子的:
[UIViewanimateWithDuration:1.0animations:^{ self.firstView.alpha=0.0; self.secondView.alpha=1.0; }];
如果用C#来实现的话,应该是这样:
UIView.Animate(1.0,()=>{ this.FirstView.Alpha=0.0f; this.SecondView.Alpha=1.0f; });
这样就实现了一个简单的渐变动画,并且只能运行一次,通常不能满足需求,再来一个复杂点儿的:
[UIViewanimateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.firstView.alpha=0.0; } completion:^(BOOLfinished){ [UIViewanimateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseOutanimations:^{ self.firstView.alpha=1.0; } completion:nil]; }];
对应的C#代码如下:
UIView.Animate( 1.0, 0.0, UIViewAnimationOptions.CurveEaseIn, ()=>this.FirstView.Alpha=0.0f, ()=>{ UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.CurveEaseOut, ()=>this.FirstView.Alpha=1.0f, null ); } );
嵌套动画
iOS支持嵌套的动画,也就是说在一个动画代码段中,可以再开始另外一个动画代码段,而不必等当前动画完成,嵌套的动画会同时开始运行,默认继承原来动画的延时、时间长度、加速曲线等,不过这些选项也能被覆盖。例如:
[UIViewanimateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseOutanimations:^{ self.firstView.alpha=0.0f; //这里开始一个新的动画 [UIViewanimateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionOverrideInheritedCurve| UIViewAnimationOptionCurveLinear| UIViewAnimationOptionOverrideInheritedDuration| UIViewAnimationOptionRepeat| UIViewAnimationOptionAutoreverse animations:^{ [UIViewsetAnimationRepeatCount:2.5]; self.secondView.alpha=0.0f; } completion:nil]; } completion:nil ];
对应的C#代码如下:
UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.CurveEaseIn, ()=>{ this.FirstView.Alpha=0.0; UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.OverrideInheritedCurve| UIViewAnimationOptions.CurveLinear| UIViewAnimationOptions.OverrideInheritedDuration| UIViewAnimationOptions.Repeat| UIViewAnimationOptions.Autoreverse, ()=>{ UIView.SetAnimationRepeatCount(2.f); this.SecondView.Alpha=0.0; }, null ); }, null );
对于使用Begin/Commit方法的动画,也可以嵌套调用Begin/Commit方法来实现嵌套的动画,例如:
UIView.BeginAnimations("Animation1"); //Animationcodegoeshere //Startanotheranimation UIView.BeginAnimations("Nestedanimation"); //nestedanimationscodegoeshere. UIView.CommitAnimations(); //othercode UIView.CommitAnimations();
这段C#代码对应的ObjC代码很简单,就不写出来了。
实现动画的自动翻转
当创建自动翻转指定次数的动画时,考虑将重复次数设置为非整数值。因为对于自动翻转的动画来说,每次循环都是从原始值变化到目标值再变化回原始值,如果希望动画结束之后停留在目标值,需要将重复次数设置加上0.5,否则,动画回慢慢变回原始值,再迅速变化到目标值,这可能不是原来期望的动画效果。
创建视图切换动画
视图切换动画可以减少修改可视化树时引起的界面上的突变,iOS系统中大量使用了视图切换动画,视图切换动画主要有下面两种场景:
- 修改子视图
- 替换子视图
注意:不要把视图切换和视图控制器的切换混淆(显示一个模式对话框、将视图控制器推入导航堆栈等),视图切换改变的仅仅是视图的可视化树,视图控制器是不变的,更多信息可以参考iOS视图控制器编程指南。
修改子视图
可以修改子视图的可见性用来表示当前视图的不同的状态,看下面的两个视图切换的例子,在iOS4.0之前,需要将视图切换动画添加到Begin/Commit动画之间,代码如下:
在iOS4.0之后,可以使用transitionWithView:duration:options:animations:completion:
[UIViewbeginAnimations:@"toggleView"context:nil]; [UIViewsetAnimationTransition:UIViewAnimationTransitionCurlUpforView:self.viewcache:YES]; [UIViewsetAnimationDuration:1.0]; //animationgoeshere self.currentView.hidden=YES; self.swapView.hidden=NO; [UIViewcommitAnimations];
这里只有动画部分的代码,动画完成之后请参考setAnimationDelegate:方法设置并实现UIAnimationDelegate。
替换子视图
要进行子视图的替换,需要用到transitionFromView:toView:duration:options:completion:方法,示例代码如下:
UIView*fromView=(self.displayPrimary?self.view:self.secondView); UIView*toView=(self.displayPrimary?self.secondView:self.view); UIViewAnimationOptionsoption=(self.displayPrimary?UIViewAnimationOptionTransitionFlipFromRight :UIViewAnimationOptionTransitionFlipFromLeft); [UIViewtransitionFromView:fromViewtoView:toViewduration:1.0options:option completion:^(BOOLfinished){ if(finished){ self.displayPrimary=!self.displayPrimary; } } ];
链接多个动画
有了上面的知识,链接多个动画就非常简单了:
- 对于lambda或block-based方法的动画,使用complete回调函数即可;
- 对于Begin/Commit方法的动画,需要实现一个UIAnimationDelegate,然后调用setAnimationDelegate方法设置Delegate即可。
以上就是详解iOS系统中的视图动画的详细内容,更多关于iOS视图动画的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。