UIView类本身自带了一套动画,当UIView的某个属性发生改变时,UIView会自动为其加上动画效果,当然,是否需要动画,以及怎样动画,需要我们告诉UIView;
首先了解一下,UIView的哪些属性可以用来做动画?
常用的有,坐标:frame,bounds,center;透明度:alpha;旋转:transform,颜色:backgroundColor,textColor
UIView动画,常用方法有:
@interface UIView(UIViewAnimation)
//开始动画
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
//提交动画
+(void)commitAnimations;
//设置代理
+ (void)setAnimationDelegate:(nullable id)delegate;
// default = nil 设置动画将要开始时执行的方法
// default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
//动画停止时的执行的方法
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
//设置动画时间 default = 0.2
+ (void)setAnimationDuration:(NSTimeInterval)duration;
//延迟时间 default = 0.0
+ (void)setAnimationDelay:(NSTimeInterval)delay;
// default = now ([NSDate date])
+ (void)setAnimationStartDate:(NSDate *)startDate;
//设置动画样式 default = UIViewAnimationCurveEaseInOut
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
// default = 0.0. May be fractional 设置动画重复次数
+ (void)setAnimationRepeatCount:(float)repeatCount;
// default = NO. used if repeat count is non-zero 是否自动逆向动画
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
@end
UIView动画快,一般是以beginAnimation开始,以commitAnimations结束,其他的设置在这之间.
一,平移
平移只需给定最终的坐标,动画就会执行
例如,实现这么一个动画:将view从一个位置,缓慢移动到另一个位置;可以这样实现:
//开始
[UIView beginAnimations:nil context:nil];
//设置动画时间
[UIView setAnimationDuration:2.0];
//设置结束的位置
label.frame = CGRectMake(0, 300, 100, 40);
//提交动画
[UIView commitAnimations];
就这样就实现了一个简单的平移动画!
下面实现一个在两点之间来回移动的动画,只需在上面的代码中加上两句:
//开始
[UIView beginAnimations:nil context:nil];
//设置动画时间
[UIView setAnimationDuration:2.0];
//note:设置动画重复的两句代码一定要在动画结束位置代码的前边
//设置动画是否重复来回
[UIView setAnimationRepeatAutoreverses:YES];
//设置动画重复次数,0和1都是一次,
//LONG_MAX就是无限大
[UIView setAnimationRepeatCount:LONG_MAX];
//设置结束的位置
label.frame = CGRectMake(0, 300, 100, 40);
//提交动画
[UIView commitAnimations];
需要注意的是,新加的两句代码一定要写在设置结束位置的代码的前面,否则不会有效果!
二,旋转
旋转主要是用了view的transform属性
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2];
[UIView setAnimationRepeatCount:LONG_MAX];
// CGAffineTransformMakeRotation 是一个旋转的方法,后面需要传一个旋转的角度,这个是弧度,系统会把这个弧度转化为相应的矩阵
// 此方法只能旋转一次
// 逆时针旋转加-号
CGAffineTransform trans2 = CGAffineTransformMakeRotation(M_PI);
// 让视图连续旋转,第一个参数记录上次旋转的位置,第二个参数是每次旋转的角度
CGAffineTransform trans3 = CGAffineTransformRotate(label.transform, M_PI);
// 大小的变换动画,后边传 x 和 y 的变大倍数
CGAffineTransform trans4 = CGAffineTransformMakeScale(2, 2);
label.transform = trans2;
[UIView commitAnimations];
三,转场
UIView动画也可以加在视图转场时
FirstViewController *first = [[FirstViewController alloc]init];
UIWindow *win = [[[UIApplication sharedApplication]delegate]window];
win.rootViewController = first;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
// Transition 转换 变化
// UIViewAnimationTransitionCurlUp flip 翻转 curl 卷曲
// forView:要实现翻转效果的两个视图的父视图
// cache 缓存 YES
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:win cache:YES];
[UIView commitAnimations];
四,绑方法
有时候需要在动画结束后,执行某些操作,这时,可以通过绑定动画结束方法实现,需要设置代理
//开始
[UIView beginAnimations:nil context:nil];
//设置动画时间
[UIView setAnimationDuration:2.0];
[UIView setAnimationDidStopSelector:@selector(cc)]; //绑定动画结束的方法
[UIView setAnimationDelegate:self];
//设置结束的位置
label.frame = CGRectMake(0, 300, 100, 40);
//提交动画
[UIView commitAnimations];
这样在动画结束后就会去调用cc方法;
你在底层看API的时候发现在setAnimationDidStopSelector的旁边有个注释:
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
你会感到这个注释有些奇怪;也不知道是哪路大神发现的,注释后面是一个隐藏的动画执行结束后调用的方法,这样在UIView动画里只需设置好代理,不用设置结束方法,但是要实现注释里的方法,动画在结束后就会自动调用那个方法:
-(void)animation4 {
//开始
[UIView beginAnimations:nil context:nil];
//设置动画时间
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelegate:self];
//设置结束的位置
label.frame = CGRectMake(0, 300, 100, 40);
//提交动画
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
NSLog(@"动画结束了");
}
也许你会发现,动画的开始方法beginAnimation中有两个参数, 而系统隐藏的方法里也有两个参数与之相同,两者有什么关系呢?
//第一个参数是动画的标示符,用于区分是哪个动画
//第二个参数是传递到动画结束方法的对象
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context
/**
* @author LQQ, 16-04-10 15:04:25
*
* 动画结束方法
*
* @param animationID 和开始动画的第一个参数匹配,动画的标示符,当动画有多个时,用于标识是哪个动画调用的该方法
* @param finished 不和上面的任意一个参数匹配,它标志着这个动画是否做完毕,如果finished = 1,代表完毕 如果finished = 0 ,代表此动画夭折
* @param context 和开始动画的第二个参数匹配,动画中传递的参数,从这里接收
*/
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
如果一个页面的动画比较多,可以通过animationID来区分动画,执行相应的操作,需要传递的参数可以从context获取,它是void类型,在这里相当于id类型,接收后转换为相应的类型即可!
-(void)animation4 {
//开始
/**
* @author LQQ, 16-04-10 15:04:21
* 第一个参数是动画的标示符,用于区分是哪个动画
第二个参数是传递到动画结束方法的对象
* + (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context
*/
[UIView beginAnimations:@"animation4" context:@"1234"];
//设置动画时间
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelegate:self];
//设置结束的位置
label.frame = CGRectMake(0, 300, 100, 40);
//提交动画
[UIView commitAnimations];
}
/**
* @author LQQ, 16-04-10 15:04:25
*
* 动画结束方法
*
* @param animationID 和开始动画的第一个参数匹配,动画的标示符,当动画有多个时,用于标识是哪个动画调用的该方法
* @param finished 不和上面的任意一个参数匹配,它标志着这个动画是否做完毕,如果finished = 1,代表完毕 如果finished = 0 ,代表此动画夭折
* @param context 和开始动画的第二个参数匹配,动画中传递的参数,从这里接收
*/
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if ([animationID isEqualToString:@"animation4"]) {
NSString *str = (__bridge NSString*)context;
NSLog(@"动画结束了,传递的参数是:%@",str);
}
}
输出:
[5583:421426] 动画结束了,传递的参数是:1234
在动画中通过setAnimationDidStopSelector设置 的方法,如果不是使用的系统默认的方法,需要传递参数的话,方法的格式和参数类型要和系统那个方法一致,方法名可以自定义!
UIView也提供了一些以block形式添加动画的方法
/**
* @author LQQ, 16-04-10 16:04:29
*
*
*
* @param duration 动画持续时间
* @param delay 延迟执行动画
* @param options 动画的控制类型
* @param animations 将改变视图属性的代码写在这个block中,例如:最终的坐标
* @param completion 动画结束后执行的block
*/
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
/**
* @author LQQ, 16-04-10 16:04:31
*
*
* @param duration 动画持续时间
* @param animations 将改变视图属性的代码写在这个block中,例如:最终的坐标
* @param completion 动画结束后执行的block
*/
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0
/**
* @author LQQ, 16-04-10 16:04:09
*
*
* @param duration 动画持续时间
* @param animations 动画结束后执行的block
*/
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL
/**
@param duration 动画持续时间
@param delay 延迟执行
@param dampingRatio 弹簧震动效果,范围为0-1, 数值越小, 弹簧的震动效果越明显
@param velocity 出事速度,数值越大, 开始移动速度越快
@param options 动画的类型, 是个枚举
@param animations 需要做的动画
@param completion 动画完成后的回调
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
usingSpringWithDamping:(CGFloat)dampingRatio
initialSpringVelocity:(CGFloat)velocity
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
使用block动画实现平移的动画可以这么写:
[UIView animateWithDuration:2.0 animations:^{
label.frame = CGRectMake(0, 300, 100, 40);
}];
来回平移的动画:
[UIView animateWithDuration:2.0 delay:1.0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
label.frame = CGRectMake(0, 300, 100, 40);
} completion:nil];
UIView动画commit之后如何停止?
只需使用做动画的view的layer调用如下方法:
[label.layer removeAllAnimations];
即可停止当前的UIView动画,需要导入框架 #import <QuartzCore/QuartzCore.h>
最后,介绍一种UIImageView的帧动画(类似于GIF的动画):
//设置一组帧动画图片
imgview.animationImages = array;
//设置动画持续时间
imgview.animationDuration = 1.0;
//设置动画的重复次数,0代表无限次
imgview.animationRepeatCount = 0;
//给图片视图设置一张图片
imgview.image = [UIImage imageNamed:@"plane1.png"];
//把图片视图添加到窗口上
[self.window addSubview:imgview];
//启动动画
[imgview startAnimating];