简介
- 日常开发中常使用动画,恰当地使用动画有助于提高用户体验。
- UIView动画事务提供了大量简单的接口来实现种类繁多的动画效果。
- UIView动画事务多用于执行隐式动画:
frame:设置视图大小及位置
bounds:设置视图矩形大小
center:设置视图中心点位置
transform:设置视图的纺射变幻属性(缩放、旋转)
alpha:设置视图的透明度
UIView动画事务基本要素
- 持续时间:Duration,描述了动画执行的总时间。
- 线性规律:Curve,描述了动画的执行方式,展示的效果。
- 动画类型:通过改变视图属性,生成隐式动画效果。
- 回调方法:动画委托方法或选取器方法,可以监视动画执行状态,并在相应状态执行自定义操作。
- 其他配置:UIView动画事务提供了更多的配置接口,使动画效果更多样化。
UIView动画事务的初始化及配置
- 一般方法配置动画事务
+(void)beginAnimations:(NSString *)animationID context:(void *)context;
+(void)commitAnimations;
[UIView beginAnimations:@"alpha" context:nil];
// 动画事务配置代码:
// 持续时间;
// 线性规律;
// 重复次数;
// ......
[UIView commitAnimations];
- 使用block代码块实现动画事务
+(void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
[UIView animateWithDuration:1.0 animations:^{
// 动画事务配置代码:
// 持续时间;
// 线性规律;
// 重复次数;
// ......
}];
UIView转场动画及委托回调配置
- +(void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
UIViewAnimationTransition:
UIViewAnimationTransitionNone:无转场动画类型
UIViewAnimationTransitionFlipFromLeft:页面从左向右翻转
UIViewAnimationTransitionFlipFromRight:页面从右向左翻转
UIViewAnimationTransitionCurlUp:向上翻页
UIViewAnimationTransitionCurlDown:向下翻页
设置委托
+ (void)setAnimationDelegate:(id)delegate;
动画开始回调方法
+ (void)setAnimationWillStartSelector:(SEL)selector;
动画结束回调方法
+ (void)setAnimationDidStopSelector:(SEL)selector;
动画回调方法声明(以动画结束回调为例)
// animationID:标识符,用于判断当前结束的动画是哪一个
// finished:动画结束
// context:上下文
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context;
+ (void)setAnimationDidStopSelector:(SEL)selector;
动画事务block生成回调方法
[UIView animateWithDuration:1.0 animations:^{
// 配置动画
} completion:^(BOOL finished) {
// 动画回调
}];
- Tips:
如果需要实现组合动画,对于动画事务一般生成方法,需要设置代理,并且声明回调方法,在回调方法中根据 AnimationId 判断当前结束的是哪一个动画,然后根据需求执行下一个动画方法;而对于动画事务block生成方法,无需声明回调方法,直接在 completion 块中执行动画结束后的操作即可(即执行下一个动画)。
一般动画事务生成方法
#import "UIViewAnimationsViewController.h"
// 动画持续时间
static NSTimeInterval const animationDuration = 1.0;
// animation ids
static NSString *const kUIViewAnimationTypePosition = @"position";
static NSString *const kUIViewAnimationTypeScale = @"scale";
static NSString *const kUIViewAnimationTypeRotate = @"rotate";
static NSString *const kUIViewAnimationTypeColor = @"color";
static NSString *const kUIViewAnimationTypeAlpha = @"alpha";
static NSString *const kUIViewAnimationTypeEnd = @"end";
@interface UIViewAnimationsViewController ()
{
UIView *_animationsView;
}
@property (nonatomic, copy) UIView *animationsView; /**< 动画视图 */
- (void)initializeUserInterface; /**< 初始化用户界面 */
// 1、UIView动画事务一般生成
- (void)positionAnimation;
- (void)scaleAnimation;
- (void)rotateAnimation;
- (void)colorAnimation;
- (void)alphaAnimation;
- (void)endAnimations;
// 动画结束回调方法
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context;
@end
@implementation UIViewAnimationsViewController
- (void)dealloc
{
[_animationsView release]; _animationsView = nil;
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeUserInterface];
}
#pragma mark *** Initialize methods ***
- (instancetype)init {
if (self = [super init]) {
self.title = @"ViewAnimations";
}
return self;
}
- (void)initializeUserInterface {
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.animationsView];
// 添加点击手势,触发动画
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGesture:)];
[_animationsView addGestureRecognizer:tap];
[tap release];
}
#pragma mark *** UIView动画事务一般生成 ***
/**
* 动画基本要素:持续时间,线性规律,动画类型,回调方法,其他配置
*/
- (void)positionAnimation {
// 一般动画事务生成方法
[UIView beginAnimations:kUIViewAnimationTypePosition context:nil];
// 持续时间
[UIView setAnimationDuration:animationDuration];
// 线性规律
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
// 动画回调
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
// 其他配置
// [UIView setAnimationRepeatCount:HUGE_VAL]; // 动画重复次数
// [UIView setAnimationRepeatAutoreverses:YES]; // 设置动画是否方向执行
// 动画类型
_animationsView.center = self.view.center;
// 提交动画
[UIView commitAnimations];
}
- (void)scaleAnimation {
[UIView beginAnimations:kUIViewAnimationTypeScale context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
// 动画类型
// 缩放、旋转动画使用transform属性
// _animationView.transform = CGAffineTransformScale(_animationView.transform, 1.5, 1.5);
_animationsView.transform = CGAffineTransformMakeScale(1.5, 1.5);
[UIView commitAnimations];
}
- (void)rotateAnimation {
[UIView beginAnimations:kUIViewAnimationTypeRotate context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
// 动画类型
/*
* M_PI:表示π,180度的弧度表示
* M_PI_2:M_PI / 2
* M_PI_4:M_PI / 4
* CGAffineTransformMake...:新生成一个变幻属性,覆盖之前的.
* CGAffineTransform...:在视图之前变幻属性的基础之上再进行变幻
*/
_animationsView.transform = CGAffineTransformRotate(_animationsView.transform, M_PI_2);
[UIView setAnimationRepeatCount:HUGE_VAL];
[UIView commitAnimations];
}
- (void)colorAnimation {
[UIView beginAnimations:kUIViewAnimationTypeColor context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
_animationsView.backgroundColor = [UIColor redColor];
[UIView commitAnimations];
}
- (void)alphaAnimation {
[UIView beginAnimations:kUIViewAnimationTypeAlpha context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
_animationsView.alpha = 0.5;
[UIView commitAnimations];
}
- (void)endAnimations {
[UIView beginAnimations:kUIViewAnimationTypeEnd context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
// 同一动画事务多个动画同时执行
/*
* UIView动画事务转场动画:
* UIViewAnimationTransitionCurlUp 上翻页效果
* UIViewAnimationTransitionCurlDown 下翻页效果
*/
_animationsView.backgroundColor = [UIColor blackColor];
_animationsView.alpha = 1;
_animationsView.center = CGPointMake(CGRectGetMinX(self.view.bounds) + CGRectGetMidX(_animationsView.bounds),
CGRectGetMinY(self.view.bounds) + CGRectGetMidY(_animationsView.bounds) + 64);
// CGAffineTransformIdentity:将视图的transform属性重置,清除任何放射变幻属性 *
_animationsView.transform = CGAffineTransformIdentity;
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:_animationsView cache:NO];
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if ([animationID isEqualToString:kUIViewAnimationTypePosition]) {
[self scaleAnimation];
}else if ([animationID isEqualToString:kUIViewAnimationTypeScale]){
[self rotateAnimation];
}else if ([animationID isEqualToString:kUIViewAnimationTypeRotate]){
[self colorAnimation];
}else if ([animationID isEqualToString:kUIViewAnimationTypeColor]){
[self alphaAnimation];
}else if ([animationID isEqualToString:kUIViewAnimationTypeAlpha]){
[self endAnimations];
}
}
#pragma mark *** Gestures ***
- (void)respondsToGesture:(UITapGestureRecognizer *)gesture {
NSLog(@"%@", NSStringFromSelector(_cmd));
// 1、UIView动画一般事务
[self positionAnimation];
}
#pragma mark *** Getters ***
- (UIView *)animationsView {
if (!_animationsView) {
_animationsView = [[[UIView alloc] init] autorelease];
_animationsView.bounds = CGRectMake(0, 0, 160, 160);
_animationsView.center = CGPointMake(CGRectGetMidX(_animationsView.bounds), CGRectGetMidY(_animationsView.bounds) + 64);
_animationsView.backgroundColor = [UIColor blackColor];
}
return _animationsView;
}
@end
Block实现
#import "UIViewAnimationsViewController.h"
static NSTimeInterval const animationDuration = 1.0;
@interface UIViewAnimationsViewController ()
{
UIView *_animationsView;
}
@property (nonatomic, copy) UIView *animationsView; /**< 动画视图 */
- (void)initializeUserInterface; /**< 初始化用户界面 */
// 1、UIView动画事务block生成
- (void)positionAnimationBlock;
- (void)scaleAnimationBlock;
- (void)rotateAnimationBlock;
- (void)colorAnimationBlock;
- (void)alphaAnimationBlock;
- (void)endAnimationsBlock;
@end
@implementation UIViewAnimationsViewController
- (void)dealloc
{
[_animationsView release]; _animationsView = nil;
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeUserInterface];
}
#pragma mark *** Initialize methods ***
- (instancetype)init {
if (self = [super init]) {
self.title = @"ViewAnimations";
}
return self;
}
- (void)initializeUserInterface {
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.animationsView];
// 添加点击手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGesture:)];
[_animationsView addGestureRecognizer:tap];
[tap release];
}
#pragma mark *** UIView动画事务block生成 ***
- (void)positionAnimationBlock {
/**
* animateWithDuration:持续时间
* delay:延迟
* options:可选,配置线性规律
* animations:动画类型
* completion:动画回调
*/
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
// 处理动画类型及基本配置
_animationsView.center = self.view.center;
} completion:^(BOOL finished) {
// 动画执行完后回调方法
[self scaleAnimationBlock];
}];
}
- (void)scaleAnimationBlock {
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
// _animationView.transform = CGAffineTransformScale(_animationView.transform, 1.5, 1.5);
_animationsView.transform = CGAffineTransformMakeScale(1.5, 1.5);
} completion:^(BOOL finished) {
[self rotateAnimationBlock];
}];
}
- (void)rotateAnimationBlock {
[UIView animateWithDuration:animationDuration delay:0.0 options:(UIViewAnimationOptionCurveLinear) animations:^{
_animationsView.transform = CGAffineTransformRotate(_animationsView.transform, M_PI);
} completion:^(BOOL finished) {
[self colorAnimationBlock];
}];
}
- (void)colorAnimationBlock {
[UIView animateWithDuration:animationDuration delay:0.0 options:(UIViewAnimationOptionCurveLinear) animations:^{
_animationsView.backgroundColor = [UIColor redColor];
} completion:^(BOOL finished) {
[self alphaAnimationBlock];
}];
}
- (void)alphaAnimationBlock {
[UIView animateWithDuration:animationDuration delay:0.0 options:(UIViewAnimationOptionCurveLinear) animations:^{
_animationsView.alpha = 0.5;
} completion:^(BOOL finished) {
[self endAnimationsBlock];
}];
}
- (void)endAnimationsBlock {
[UIView animateWithDuration:animationDuration delay:0.0 options:(UIViewAnimationOptionCurveLinear) animations:^{
_animationsView.center = CGPointMake(CGRectGetMinX(self.view.bounds) + CGRectGetMidX(_animationsView.bounds),
CGRectGetMinY(self.view.bounds) + CGRectGetMidY(_animationsView.bounds) + 64);
_animationsView.backgroundColor = [UIColor blackColor];
_animationsView.alpha = 1;
_animationsView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
#pragma mark *** Gestures ***
- (void)respondsToGesture:(UITapGestureRecognizer *)gesture {
NSLog(@"%@", NSStringFromSelector(_cmd));
// 1、UIView动画一般事务
[self positionAnimationBlock];
}
#pragma mark *** Getters ***
- (UIView *)animationsView {
if (!_animationsView) {
_animationsView = [[[UIView alloc] init] autorelease];
_animationsView.bounds = CGRectMake(0, 0, 160, 160);
_animationsView.center = CGPointMake(CGRectGetMidX(_animationsView.bounds), CGRectGetMidY(_animationsView.bounds) + 64);
_animationsView.backgroundColor = [UIColor blackColor];
}
return _animationsView;
}
@end
UIImageView动画
UIImageView是图片展示视图,除了展示图片功能之外,也可以用于实现动画效果。
动画配置
animationImages:设置动画图片数组
animationDuration:设置动画持续时长
animationRepeatCount:设置动画重复次数,默认为0无限次重复-
常用方法
开始执行动画
- (void)startAnimating;结束执行动画 - (void)stopAnimating;
UIImageView动画代码案例
- 初始化UIImageView动画
- (void)initializeImageAnimations {
// 持续时间
_imageAnimationsView = 5.0;
// 图片数据源,_images为存储UIImage对象的数组。
_imageAnimationsView = _images;
// 重复次数
_imageAnimationsView = 0;
// 开始动画
[_imageAnimationsView startAnimating];
}
- 触摸拖动_imageAnimationsView视图方法
// 触摸移动
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"%@", NSStringFromSelector(_cmd));
// 根据移动的轨迹移动图片视图
UITouch *touch = [touches anyObject];
if (touch.view == _imageAnimationsView) {
// 获取上一个点
CGPoint previousLocation = [touch previousLocationInView:_imageAnimationsView];
// 获取当前点
CGPoint currentLocation = [touch locationInView:_imageAnimationsView];
// 获取偏移
CGPoint offset = CGPointMake(currentLocation.x - previousLocation.x, currentLocation.y - previousLocation.y);
// 更新图片视图中心点
_imageAnimationsView.center = CGPointMake(_imageAnimationsView.center.x + offset.x, _imageAnimationsView.center.y + offset.y);
}
}
动画事件
有时需要在某一个视图执行动画的过程中(比如位置移动)实现点击效果,如果通过添加手势的方式,会发现,即使开启了用户交互userInteractionEnabled也不会达到预期的效果,这是由于UIView动画事务执行的是隐式动画,因此不能通过手势的方式,而应该通过触摸的方式处理逻辑,此处模拟动画在移动过程中实现点击效果,animatingView为添加UIView动画事务移动的的动画。直接上关键代码;
#pragma mark *** Touches ***
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
if ([self.animatingView.layer.presentationLayer hitTest:location]) {
NSLog(@"User clicked view.");
}
}