概述
在AppStore中的应用越来越重视动画效果的使用,一个良好动画效果可以让两个状态之间平滑地过度,也可以利用动画吸引住用户的眼球,在UIView类中共有三个类目(Category)用于实现动画功能,分为UIViewAnimation、UIViewAnimationWithBlocks以及UIViewKeyframeAnimations,他们是Apple对核心动画(Core Animation)的封装,可以让我们不进行任何绘画等复杂操作的前提下实现大部分动画需求
UIView动画的用处
UIView类中提供的动画功能,允许我们实现如下动画需求
- 动态修改”可动画属性”
- frame(位置及大小)
- bounds(大小)
- center(中心点位置)
- transform(形变)
- alpha(透明度)
- backgroundColor(背景颜色)
- contentStretch(可拉伸区域,从iOS6开始被废弃)
- 提供转场动画效果
- 修改已存在视图的子视图(也可以修改自身)
- 在视图层级中用一个视图替换另一个视图(Block动画提供)
本文中样例素材
在介绍UIView动画的过程中,我们会使用一个UIImageView图片为例,对各动画效果进行演示
@property (nonatomic, strong) UIImageView *demoImageView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.demoImageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, [[UIScreen mainScreen] bounds].size.width-40, [[UIScreen mainScreen] bounds].size.height-40)];
self.demoImageView.image = [UIImage imageNamed:@"old"];
[self.view addSubview:self.demoImageView];
}
UIViewAnimation
Apple自iOS2开始提供了若干UIView的类方法来实现动画功能,Apple建议从iOS4系统开始尽量使用Block方式来实现动画功能,因此我们以后在开发中应该遵从Apple的建议使用Block方式来实现动画功能,但是学习本部分对未来学好Block动画有很好的铺垫作用,因此本文在这里会对系统提供的方法进行详尽地介绍
在iOS4之前,我们需要使用动画块(begin/commit animation block)来进行动画,一个完整的动画块由以下四部分组成
- 动画块开始标识
- 配置动画选择项
- 修改可动画属性
- 动画块结束标识
动画块开始标识
标识动画块的开始,该方法是告诉系统将要执行一个或多个动画,如果通过setAnimationWillStartSelector:或者setAnimationDidStopSelector:方法设置了代理回调方法,便可以在回调方法中收到该方法中的两个参数animationID(动画标志)和context(上下文,一般为nil)
// 格式
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
// 样例
[UIView beginAnimations:@"demo" context:nil];
动画块结束标识
标识动画块的结束,同时安排动画执行
// 格式
+ (void)commitAnimations;
// 样例
[UIView commitAnimations];
设置动画代理对象及代理回调方法
设置动画代理对象,以便在动画开始和结束时收到系统回调
// 格式
+ (void)setAnimationDelegate:(nullable id)delegate;
// 样例
[UIView setAnimationDelegate:self];
设置动画将要开始时调用代理对象的方法
// 格式
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
// 样例
[UIView setAnimationWillStartSelector:@selector(animationWillStart:context:)];
注1: 当动画当前不可用时,该方法不会被调用
注2: 当不设置该方法时,系统默认会调用- (void)animationWillStart:(NSString )animationID context:(void )context
设置动画已经结束后调用代理对象的方法
// 格式
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
// 样例
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
注1: 当动画当前不可用时,该方法依然会被调用
注2: 当不设置该方法时,系统默认会调用- (void)animationDidStop:(NSString )animationID finished:(NSNumber )finished context:(void *)context
设置动画持续时长
设置动画持续时长,默认0.2s
// 格式
+ (void)setAnimationDuration:(NSTimeInterval)duration;
// 样例
[UIView setAnimationDuration:0.2f];
注: 该方法必须在修改”可变化属性”之前调用
设置延时动画时长
设置延时动画时长,默认0.0s
// 格式
+ (void)setAnimationDelay:(NSTimeInterval)delay;
// 样例
[UIView setAnimationDelay:0.0f];
注: 该方法必须在修改”可变化属性”之前调用
设置动画开始时间(该方法设置后整个动画即不生效,不明原因)
设置动画开始时间,默认当前时间
// 格式
+ (void)setAnimationStartDate:(NSDate *)startDate;
// 样例
[UIView setAnimationStartDate:[NSDate date]];
注1: 该方法必须在修改”可变化属性”之前调用
注2: 不要在Block动画中调用该方法
注3: 该方法设置后整个动画即不生效,作者尝试过如下四种方式,结果都不生效
[UIView setAnimationStartDate:[NSDate date]];
[UIView setAnimationStartDate:[NSDate dateWithTimeIntervalSinceReferenceDate:CFAbsoluteTimeGetCurrent()]];
[UIView setAnimationStartDate:[NSDate dateWithTimeIntervalSinceNow:3]];
[UIView setAnimationStartDate:[NSDate dateWithTimeIntervalSinceReferenceDate:CFAbsoluteTimeGetCurrent()+3]];
设置时间函数
时间函数即动画进行速度随着时间的变化曲线,系统采用一个枚举类型来保存
/**
typedef NS_ENUM(NSInteger, UIViewAnimationCurve)
{
UIViewAnimationCurveEaseInOut // 默认,淡入淡出,先慢后快再慢
UIViewA