IOS开发系列——UIView专题之二:动画篇
2UIView动画
2.1概述
UIView视图的动画功能,可以使在更新或切换视图时有放缓节奏、产生流畅的动画效果,进而改善用户体验。UIView可以产生动画效果的变化包括:
•位置变化:在屏幕上移动视图。
•大小变化:改变视图框架(frame)和边界。
•拉伸变化:改变视图内容的延展区域。
•改变透明度:改变视图的alpha值。
•改变状态:隐藏或显示状态。
•改变视图层次顺序:视图哪个前哪个后。
•旋转:即任何应用到视图上的仿射变换(transform)。
UIKit直接将动画集成到UIView类中,实现简单动画的创建过程。UIView类定义了几个内在支持动画的属性声明,当这些属性发生改变时,视图为其变化过程提供内建的动画支持。
执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码包装到一个代码块中。
2.2UIView动画简单创建方法
- (void)buttonPressed
{
//交换本视图控制器中2个view位置
[self.viewexchangeSubviewAtIndex:0 withSubviewAtIndex:1];
//UIView开始动画,第一个参数是动画的标识,第二个参数附加的应用程序信息用来传递给动画代理消息
[UIViewbeginAnimations:@"View Flip" context:nil];
//动画持续时间
[UIViewsetAnimationDuration:1.25];
//设置动画的回调函数,设置后可以使用回调方法
[UIViewsetAnimationDelegate:self];
//设置动画曲线,控制动画速度
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
//设置动画方式,并指出动画发生的位置
[UIViewsetAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
//提交UIView动画
[UIViewcommitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//主要功能通过UIView动画完成2个试图控制器的切换
self.blueController =[[BlueViewController alloc] initWithNibName:nil bundle:nil];
//设置导航控制器view的大小占整个屏幕
[self.blueController.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
self.yellowController =[[YellowController alloc]initWithNibName:nil bundle:nil ];
[self.yellowController.view setFrame:CGRectMake(0, 0,self.view.frame.size.width , self.view.frame.size.height)];
//将2个控制器view插入到目前导航控制器视图上,yellowController后插入,显示在最前面
[self.viewinsertSubview:self.blueController.view atIndex:0];
[self.viewinsertSubview:self.yellowController.view atIndex:1];
//创建导航控制器右按钮,按钮名字叫next
//添加buttonPressed事件
self.rightBarItem =[[UIBarButtonItem alloc] initWithTitle:@"next" style:UIBarButtonItemStylePlaintarget:self action:@selector(buttonPressed)];
//将按钮添加到导航控制器默认右按钮上
self.navigationItem.rightBarButtonItem = self.rightBarItem;
}
有个问题:如果动画不放在按钮事件中,直接放到viewDidLoad里,程序首先执行这个controller,这时动画是不会显示的。
原因:出现这个问题是因为开机时候系统有个动画,系统动画和这个动画重复了。
解决方案:
1、将动画写在按钮事件中
2、利用定时器。
转:UIView动画更具体讲解;http://wsqwsq000.iteye.com/blog/1189183
2.3创建UIView动画(块)——(指过渡效果的动画)
2.3.1一.基本方式:使用UIView类的UIViewAnimation扩展
UIView动画是成块运行的。发出beginAnimations:context:请求标志着动画块的开始;commitAnimations标志着动画块的结束。把这两个类方法发送给UIView而不是发送给单独的视图。在这两个调用之间的可定义动画的展现方式并更新视图。函数说明:
//开始准备动画
+ (void)beginAnimations:(NSString *)animationID context:(void*)context;
//运行动画
+ (void)commitAnimations;
具体二段动画代码:
[UIView beginAnimations:nil context:nil];
//setAnimationCurve来定义动画加速或减速方式
[UIView setAnimaitonCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:2.7];//动画时长
[UIView setAnimationTransition:transitionforView:self.view cache:YES];
// operation>>>
[self.view exchangeSubviewAtIndex:0withSubviewAtIndex:1];
// end<<<<<
[UIView commitAnimations];
CGContextRef context = UIGraphicsGetCurrentContext();//返回当前视图堆栈顶部的图形上下文
[UIView beginAnimations:nil context:context];
[UIView setAnimaitonCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
// View changes go here
[contextView setAlpha:0.0f];
[UIView commitAnimations];
其中transition取值范围:UIView类本身提供四种过渡效果
UIViewAnimationTransitionNone正常
UIViewAnimationTransitionFlipFromLeft从左向右翻
UIViewAnimationTransitionFlipFromRight从右向左翻
UIViewAnimationTransitionCurlUp从下向上卷
UIViewAnimationTransitionCurlDown从上向下卷
2.3.2二.block方式:使用UIView类的UIViewAnimation WithBlocks扩展
要用到的函数有:
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay
options:(UIViewAnimationOptions)options animations:(void(^)(void))animations
completion:(void(^)(BOOL finished))completion
__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
//间隔,延迟,动画参数(好像没用?),界面更改块,结束块
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations
completion:(void(^)(BOOL finished))completion
__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
// delay = 0.0, options = 0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations
__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
// delay = 0.0, options = 0, completion =
NULL
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options animations:(void(^)(void))animations
completion:(void(^)(BOOL finished))completion
__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView
duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options
completion:(void(^)(BOOL finished))completion
__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
// toView added to fromView.superview,
fromView removed from its superview界面替换,这里的options参数有效
2.3.3三.core方式:使用CATransition类
iPhone还支持Core Animation作为其QuartzCore架构的一部分,CA API为iPhone应用程序提供了高度灵活的动画解决方案。但是须知:CATransition只针对图层,不针对视图。图层是Core Animation与每个UIView产生联系的工作层面。使用Core Animation时,应该将CATransition应用到视图的默认图层([myView layer])而不是视图本身。
使用CATransition类实现动画,只需要建立一个Core Animation对象,设置它的参数,然后把这个带参数的过渡添加到图层即可。
使用要引入QuartzCore.framework代码
#import
示例代码:
CATransition *transition = [CATransition
animation];
transition.duration =0.7;
transition.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;//{kCATransitionMoveIn, kCATransitionPush,kCATransitionReveal, kCATransitionFade};
//更多私有{@"cube",@"suckEffect",@"oglFlip",@"rippleEffect",@"pageCurl",@"pageUnCurl",@"cameraIrisHollowOpen",@"cameraIrisHollowClose"};
transition.subtype =
kCATransitionFromLeft;//{kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop,kCATransitionFromBottom};
transition.delegate= self;
[self.view.layer addAnimation:transition forKey:nil];
//要做的
[self.view exchangeSubviewAtIndex:1withSubviewAtIndex:0];
CATransition动画使用了类型type和子类型subtype两个概念。type属性指定了过渡的种类(淡化、推挤、揭开、覆盖)。subtype设置了过渡的方向(从上、下、左、右)。另外,CATransition私有的动画类型有(立方体、吸收、翻转、波纹、翻页、反翻页、镜头开、镜头关)。
2.4API简介
areAnimationsEnabled
返回一个布尔值表示动画是否结束。
+ (BOOL)areAnimationsEnabled
返回值
如果动画结束返回YES,否则NO。
beginAnimations:context:
开始一个动画块
+ (void)beginAnimations:(NSString*)animationID context:(void *)context
参数
animationID
动画块内部应用程序标识用来传递给动画代理消息-这个选择器运用setAnimationWillStartSelector:和setAnimationDidStopSelector:方法来设置。
context
附加的应用程序信息用来传递给动画代理消息-这个选择器使用setAnimationWillStartSelector:和setAnimationDidStopSelector:方法。
讨论
这个值改变是因为设置了一些需要在动画块中产生动画的属性。动画块可以被嵌套。如果在没有在动画块中调用那么setAnimation类方法将什么都不做。使用beginAnimations:context:来开始一个动画块并用commitAnimations类方法来结束一个动画块。
commitAnimations
结束一个动画块并开始当他在动画块外时。
+ (void)commitAnimations
讨论
如果当前的动画块是最外层的动画块,当应用程序返回到循环运行时开始动画块。动画在一个独立的线程中所有应用程序不会中断。使用这个方法,多个动画可以被实现。查看setAnimationBeginsFromCurrentState:来了解如果开始一个动画当另外一个动画在播放的时候。
layerClass
返回类用来创建这一个本类的layer实例对象。
+ (Class)layerClass
返回值
一个用来创建视图layer的类
讨论
重写子类来指定一个自定义类用来显示。当在创建视图layer时候调用。默认的值是CALayer类对象。
setAnimationBeginsFromCurrentState:
设置动画从当前状态开始播放。
+(void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState
参数
fromCurrentState
YES如果动画需要从他们当前状态开始播放。否则为NO。
讨论
如果设置为YES那么当动画在运行过程中,当前视图的位置将会作为新的动画的开始状态。如果设置为NO,当前动画结束前新动画将使用视图最後状态的位置作为开始状态。这个方法将不会做任何事情如果动画没有运行或者没有在动画块外调用。使用beginAnimations:context:类方法来开始并用commitAnimations类方法来结束动画块。默认值是NO。
setAnimationCurve:
设置动画块中的动画属性变化的曲线。
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve
讨论
动画曲线是动画运行过程中相对的速度。如果在动画块外调用这个方法将会无效。使用beginAnimations:context:类方法来开始动画块并用commitAnimations来结束动画块。默认动画曲线的值是UIViewAnimationCurveEaseInOut。
setAnimationDelay:
在动画块中设置动画的延迟属性(以秒为单位)
+(void)setAnimationDelay:(NSTimeInterval)delay
讨论
这个方法在动画块外调用无效。使用beginAnimations:context:类方法开始一个动画块并用commitAnimations类方法结束动画块。默认的动画延迟是0.0秒。
setAnimationDelegate:
设置动画消息的代理。
+ (void)setAnimationDelegate:(id)delegate
参数
delegate
你可以用setAnimationWillStartSelector:和setAnimationDidStopSelector:方法来设置接收代理消息的对象。
讨论
这个方法在动画块外没有任何效果。使用beginAnimations:context:类方法开始一个动画块并用commitAnimations类方法结束一个动画块。默认值是nil
setAnimationDidStopSelector:
设置消息给动画代理当动画停止的时候。
+(void)setAnimationDidStopSelector:(SEL)selector
参数
selector
当动画结束的时候发送给动画代理。默认值是NULL。这个选择者须有下面方法的签名:animationFinished:(NSString *)animationID
finished:(BOOL)finished context:(void *)context。
animationID
一个应用程序提供的标识符。和传给beginAnimations:context:相同的参数。这个参数可以为空。
finished
如果动画在停止前完成那返回YES;否则就是NO。
context
一个可选的应用程序内容提供者。和beginAnimations:context:方法相同的参数。可以为空。
讨论
这个方法在动画块外没有任何效果。使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations类方法结束。默认值是NULL。
setAnimationDuration:
设置动画块中的动画持续时间(用秒)
+(void)setAnimationDuration:(NSTimeInterval)duration
参数
duration
一段动画持续的时间。
讨论
这个方法在动画块外没有效果。使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations类方法来结束一个动画块。默认值是0.2。
setAnimationRepeatAutoreverses:设置动画块中的动画效果是否自动重复播放。
+(void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses
参数
repeatAutoreverses
如果动画自动重复就是YES否则就是NO。
讨论
自动重复是当动画向前播放结束後再重头开始播放。使用setAnimationRepeatCount:类方法来指定动画自动重播的时间。如果重复数为0或者在动画块外那将没有任何效果。使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations方法来结束一个动画块。默认值是NO。
setAnimationRepeatCount:
设置动画在动画模块中的重复次数
+(void)setAnimationRepeatCount:(float)repeatCount
参数
repeatCount
动画重复的次数,这个值可以是分数。
讨论
这个属性在动画块外没有任何作用。使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations类方法来结束。默认动画不循环。
setAnimationsEnabled:
设置是否激活动画
+ (void)setAnimationsEnabled:(BOOL)enabled
参数
enabled
如果是YES那就激活动画;否则就是NO
讨论
当动画参数没有被激活那么动画属性的改变将被忽略。默认动画是被激活的。
setAnimationStartDate:
设置在动画块内部动画属性改变的开始时间
+ (void)setAnimationStartDate:(NSDate*)startTime
参数
startTime
一个开始动画的时间
讨论
使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations类方法来结束动画块。默认的开始时间值由CFAbsoluteTimeGetCurrent方法来返回。
setAnimationTransition:forView:cache:在动画块中为视图设置过渡
+ (void)setAnimationTransition:(UIViewAnimationTransition)transitionforView:(UIView *)view cache:(BOOL)cache
参数
transition
把一个过渡效果应用到视图中。可能的值定义在UIViewAnimationTransition中。
view
需要过渡的视图对象。
cache
如果是YES,那么在开始和结束图片视图渲染一次并在动画中创建帧;否则,视图将会在每一帧都渲染。例如缓存,你不需要在视图转变中不停的更新,你只需要等到转换完成再去更新视图。
讨论
如果你想要在转变过程中改变视图的外貌。举个例子,文件从一个视图到另一个视图,然後使用一个UIView子类的容器视图,如下:
1.Begin an animation block.
2.Set the transition on the container view.
3.Remove the subview from the containerview.
4.Add the new subview to the containerview.
5.Commit the animation block.
1.开始一个动画块。2.在容器视图中设置转换。3.在容器视图中移除子视图。4.在容器视图中添加子视图。5.结束动画块。
setAnimationWillStartSelector:
当动画开始时发送一条消息到动画代理
+(void)setAnimationWillStartSelector:(SEL)selector
参数
selector
在动画开始前向动画代理发送消息。默认值是NULL。这个selector必须由和beginAnimations:context:方法相同的参数,一个任选的程序标识和内容。这些参数都可以是nil。
讨论
这个方法在动画块外没有任何作用。使用beginAnimations:context:类方法来开始一个动画块并用commitAnimations类方法来结束。
2.5简单动画效果示例
2.5.1简单移动
imageView.transform =CGAffineTransformIdentity;
imageView.frame=CGRectMake(0, 100, 320,320);
[UIView beginAnimations:@"clearmemory"context:imageView];
[UIView setAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton)];
imageView.frame=CGRectMake(34, 0, 320,320);
[UIView commitAnimations];
2.5.2动画曲线
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
//UIViewAnimationCurveEaseInOut, // slow at beginningand end
//UIViewAnimationCurveEaseIn, // slowat beginning
//UIViewAnimationCurveEaseOut, // slow atend
//UIViewAnimationCurveLinear
//恒定速度
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
imageView.frame=CGRectMake(22, 0, 320, 320);
[UIView commitAnimations];
2.5.3反向重复
[UIViewbeginAnimations:@"animation3" context:imageView1];
[UIViewsetAnimationCurve:UIViewAnimationCurveLinear];
[UIViewsetAnimationDuration:1.0];
[UIViewsetAnimationRepeatAutoreverses:YES];
[UIViewsetAnimationRepeatCount:10];
[UIViewsetAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(enablebutton:)];
imageView1.alpha=0;
[UIViewcommitAnimations];
2.5.4延时,缓入,缓出
[UIView beginAnimations:nilcontext:nil];
[UIViewsetAnimationDelay:0.5];
[UIViewsetAnimationDuration:1.5];
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
[UIViewsetAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:2];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
imageView.frame=CGRectMake(120, 0, 200, 200);
[UIView commitAnimations];
//缓出
[UIView beginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseOut];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
imageView.frame=CGRectMake(235, 144, 200 , 200);
[UIView commitAnimations];
2.5.5放大
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationCurve:UIViewAnimationCurveLinear];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
imageView.transform=CGAffineTransformMakeScale(2,2);
[UIView commitAnimations];
//旋转放大这里用到179.9是因为你不管前面加-+都是逆时针
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationCurve:UIViewAnimationCurveLinear];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
CGAffineTransformtranform1=CGAffineTransformMakeScale(1, 1);
CGAffineTransformtranform3=CGAffineTransformMakeTranslation(200, 200);
CGAffineTransformtranform2=CGAffineTransformMakeRotation(179.9*M_PI/180.0);
imageView.transform=CGAffineTransformConcat(tranform1, tranform3);
[UIView commitAnimations];
2.5.6平移旋转
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
CGAffineTransformtranform1=CGAffineTransformMakeTranslation(-200, 0);
// CGAffineTransformtranform2= CGAffineTransformMakeRotation(179.9*M_PI/180.0);
imageView.transform=CGAffineTransformRotate(tranform1, 359.9*M_PI/180.0);
[UIView commitAnimations];
2.5.7翻转
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:1];
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
[UIViewsetAnimationTransition:UIViewAnimationTransitionFlipFromRightforView:self.viewcache:YES];
//UIViewAnimationTransitionFlipFromLeft从左往右翻
//UIViewAnimationTransitionFlipFromRight从右往左翻
//UIViewAnimationTransitionCurlUp从上往下翻
//UIViewAnimationTransitionCurlDown从下往上翻
[UIViewsetAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(enablebutton:)];
imageView.hidden=YES;
imageView1.hidden=NO;
[UIView commitAnimations];
2.5.8淡入淡出
CATransition *animation = [CATransitionanimation];
animation.duration = 0.75f; //动画时长
animation.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation.delegate = self;
animation.type = kCATransitionFade; //过度效果
//kCATransitionFade淡入淡出
//kCATransitionMoveIn移入移出
//kCATransitionPush压入推出
//kCATransitionReveal覆盖移除
animation.subtype=kCATransitionFromLeft;
//kCATransitionFromRight从左
//kCATransitionFromLeft从右
//kCATransitionFromTop从上
//kCATransitionFromBottom从下
[self.view.layer addAnimation:animationforKey:@"animation"];
imageView.hidden=YES;
imageView1.hidden=NO;
-(void)enablebutton:(id)sender
{
imageView.transform=CGAffineTransformIdentity;
imageView.frame=CGRectMake(0,0, 200, 200);
//btn.enabled=NO;
}
2.5.9点击缩略图到大图的过场动画
CGRectframe = [smallImgView.superviewconvertRect: smallImgView.frametoView:self.window];
//后续有入场动画
_coverView=
[[UIScrollViewalloc]initWithFrame:frame];
//增加入场动画
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:0.25];
_coverView.frame=CGRectMake(0,0,ESScrnW,ESScrnH);
[UIViewcommitAnimations];