四:动画技术一

UIView动画和Core Animation框架,事实上IOS动画的核心技术是Core Animation(缩写为CA),而UIView动画本质上也是Core Animation框架实现的,只不过进行了封装和优化。此外,本章还介绍IOS7新动画相关技术UIKit力学(UIKit Dynamics)和运动效果(Motion Effects).

4.1 视图动画

每个视图都关联到一个图层(CALayer)对象,视图主要用来处理事件,图层用来处理动画,视图上所有动画、绘制和可视效果都直接或间接地由层处理。

视图由一系列支持动画的属性,包括frame、bounds、center、alpha和transform等。此外,还有一些属性如下:动画延迟事件、动画曲线(淡入/淡出、淡入、淡出和线性等)、动画过渡、重复次数和自动反转等属性。

4.1.1 动画块

动画效果的对应属性设定是放在动画块中的,在IOS4.0之前我们是通过UIView下面方法设置动画块的。

[UIView beginAnimations:@"animations" context:nil];
...
[UIView commitAnimations];

在IOS4.0之后又推出了采用代码块(Block)的方法,这些UIView方法如下:

  • +(void)animateWithDuration:delay:options:animations:completion:
  • +(void)animateWithDuration: animations:completion:
  • +(void)animateWithDuration:animations:

这些方法都是UIView的类方法,需要实例化就可以直接调用,其中animationWithDuration后面的参数是动画持续的时间,animations:后面是一个代码块,用来设置动画的属性。completion:也上一个代码块,是在动画结束时候调用执行的。delay:后面是动画延迟的时间,如果为0则动画马上执行

下面通过一个实例介绍一下动画块的使用,以及动画处理的过程。这个实力如图所示,在屏幕上有一个球形图片和一个Tap Me的按钮,当用户单击Tap Me按钮时,球体向下移动100点,持续时间是1.5秒。当再次单击Tap Me按钮的时候,球体向上移动100个点,就这样反复运动。

这里写图片描述

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end
#import "ViewController.h"

@interface ViewController ()
{
    int flag ;
}

@property (weak, nonatomic) IBOutlet UIImageView *ball;
- (IBAction)click:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    flag = 1;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)click:(id)sender {
    /*
     [UIView beginAnimations:@"animations" context:nil];

     [UIView setAnimationDuration:1.5];

     CGRect frame = self.ball.frame;
     frame.origin.y += 100 * flag;
     flag *= -1; //取反
     self.ball.frame = frame;

     [UIView commitAnimations];

     */


    [UIView animateWithDuration:1.5 animations:^{
        CGRect frame = self.ball.frame;
        frame.origin.y += 100 * flag;
        flag *= -1; //取反
        self.ball.frame = frame;
    }];
}

@end

4.1.2 动画生命周期事件

有的时候,需要捕获动画开始与结束事件,iOS4.0之前采用的beginAnimation:和commitAnimations方法时我们可以设置动画委托对象,然后再通过下面方法设置动画开始后的回调方法。

+(void)setAnimationWillStartSelector:(SEL)selector

下面方法时设置动画结束后的回调方法

+(void)setAnimationDidStopSelector:(SEL)selector

而在iOS4.0之后,如果采用下面方法实现动画功能时,可以completion:实现动画结束的处理。但这些方法并没有动画开始的代码块

+animateWithDuration:animations:completion:
+animateWithDuration:delay:options:animations:completion:

下面通过一个实例介绍它们的用法。在上个实例上进行了修改,当单击Tap Me按钮时候按钮小时,动画开始。当动画结束的时候,Tap Me按钮又显示出来了。
这里写图片描述

iOS4.0之前的代码

- (IBAction)click:(id)sender {

    [self.button setAlpha:0.0];

    [UIView beginAnimations:@"animations" context:nil];

    [UIView setAnimationDuration:1.5];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(viewAnimationDone)];

    CGRect frame = self.ball.frame;
    frame.origin.y += 100 * flag;
    flag *= -1; //取反
    self.ball.frame = frame;

    [UIView commitAnimations];

}


- (void)viewAnimationDone {
    [UIView beginAnimations:@"animationDone" context:nil];
    [self.button setAlpha:1.0];
    [UIView commitAnimations];
}

iOS4.0之后的代码

- (IBAction)click:(id)sender {

    [self.button setAlpha:0.0];

    [UIView animateWithDuration:1.5 animations:^{
        CGRect frame = self.ball.frame;
        frame.origin.y += 100 * flag;
        flag *= -1; //取反
        self.ball.frame = frame;
    } completion:^(BOOL finished) {
        NSLog(@"动画结束了。");
        [self viewAnimationDone];
    }];

}


- (void)viewAnimationDone {
    [UIView animateWithDuration:1. animations:^{
        [self.button setAlpha:1.0];
    }];
}

4.1.3 过渡动画

前文中提及的动画还有很多属性,例如动画曲线、过渡(界面跳转)动画、重复次数和自动反转等重要的属性,其中有一些事适用于过渡动画(Animation Transition)技术的,如动画曲线属性等。下面通过一个实例介绍过渡动画的属性使用。
这里写图片描述

- (IBAction)doUIViewAnimation:(id)sender {

    [UIView beginAnimations:@"animationID" context:nil];
    [UIView setAnimationDuration:3.0f];
    // 设置动画曲线 动画曲线是设置动画过渡执行速度的变化情况
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    // 不重复动画
    [UIView setAnimationRepeatAutoreverses:NO];

    UIButton *theButton = (UIButton *)sender;
    switch (theButton.tag) {
        case 1:
        // 第一个参数定义动画过渡类型 第二个参数事当前视图对象  第三个参数事是否适用缓存区
            [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
            break;
        case 2:
            [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
            break;
        case 3:
            [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
            break;
        case 4:
            [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
            break;
        default:
            break;
    }
    [UIView commitAnimations];

}

doUIViewAnimation:方法实现动画的处理,其中参数UIVIewAnimationCurveEaseOut是在枚举UIViewAnimationCurve中定义的常量,相关的常量还有:

UIViewAnimationCurveEaseInOut,  //缓入缓出 即开始和结束时减速
UIViewAnimationCurveEaseIn,     //缓入,开始时减速
UIViewAnimationCurveEaseOut,    //缓出,结束时减速
UIViewAnimationCurveLinear      //线性,即匀速运动

setAnimationTransition:forView:cache:方法的第一个参数定义动画过渡类型,第二个参数是当前视图对象,第三个参数是是否使用缓冲区。动画过渡类型相关的常量有:

  • UIViewAnimationTransitionNone,不设置过渡动画
  • UIViewAnimationTransitionFlipFromLeft,设置从左往右翻转
  • UIViewAnimationTransitionFlipFromRight,设置从右往左翻转
  • UIViewAnimationTransitionCurlUp,设置向上翻页
  • UIViewAnimationTransitionCurlDown,设置向下翻页

在iOS4.0之后,专门为动画过渡添加了两个方法:

  • +transitionWithView:duration:options:animations:completion:在指定的视图容器内创建动画过渡
  • +transitionFormView:toView:duration:option:completion:在指定的两个视图之间创建动画过渡

在上面的两个方法中options参数是设置动画如何执行的常量(UIViewAnimationOptions),UIViewAnimationOptions中有很多常量,其中有关于动画曲线的常量有:

  • UIViewAnimationOptionCurveEaseInOut
  • UIViewAnimationOptionCurveEaseIn
  • UIViewAnimationOptionCurveEaseOut
  • UIViewAnimationOptionCurveLinear

有关动画过渡的常量有

  • UIViewAnimationOptionTransitionNone
  • UIViewAnimationOptionTransitionFlipFromLeft
  • UIViewAnimationOptionTransitionFlipFromRight
  • UIViewAnimationOptionTransitionCurlUp
  • UIViewAnimationOptionTransitionCurlDown
  • UIViewAnimationOptionTransitionCrossDissolve
  • UIViewAnimationOptionTransitionFlipFromTop
  • UIViewAnimationOptionTransitionFlipFromBottom

主要代码有:

- (IBAction)doUIViewAnimation:(id)sender {

    UIButton *theButton = (UIButton *)sender;
    switch (theButton.tag) {
        case 1:
            [UIView transitionWithView:self.view duration:3.0f
                               options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionFlipFromLeft
                            animations:NULL completion:NULL];
            break;
        case 2:
            [UIView transitionWithView:self.view duration:3.0f
                               options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionFlipFromRight
                            animations:NULL completion:NULL];
            break;
        case 3:
            [UIView transitionWithView:self.view duration:3.0f
                               options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionCurlUp
                            animations:NULL completion:NULL];
            break;
        case 4:
            [UIView transitionWithView:self.view duration:3.0f
                               options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionCurlDown
                            animations:NULL completion:NULL];
            break;
    }

}

如果options参数很多在不发生冲突的情况下可以按位或运算,options参数写法如下:

UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionCurlDown

4.2 iOS7自定义视图过渡动画

iOS7允许用户自定义视图过渡动画

视图过渡即视图之间的跳转有两种情况:树形结构导航和模态导航,树形结构导航是通过UINavigationController控制视图堆栈实现视图过渡,模态导航是通过UIViewController控制视图实现的。由于这两种不同的过渡,因此在iOS7中自定义视图过渡也有两种不同的场景。

4.2.1 树形结构导航自定义过渡动画

在iOS7中树形结构导航自定义过渡动画涉及实现两个协议:UIViewControllerAnimatedTransitioning和UINavigationControllerDelegate。我们想要自己定义动画对象,这个对象要求实现UIViewControllerAnimatedTransitionging协议,UIView
ControllerAnimatedTransitioning主要定义了两个方法:

animateTransition:(id<UIViewControllerContextTransitioning>)tc,执行自定义动画

transitionDuration:(id<UIViewControllerContextTransitioning>),设置动画执行的时间

这两个方法中的UIViewControllerContextTransitioning类封装过渡动画的上下文对象,我们可以通过这个上下文对象获得过渡前后的视图控制器,相关代码如下:

UIViewController *fromVC = [transitionContext ViewControllerForKey:UITransitionContextFromViewControllerKey];

UIViewController *toVC = [transitionContext ViewControllerForKey:UITransitionContextToViewControllerKey];

下面的代码是实现UIViewControllerAnimatedTransitioning协议的,我们自定义过渡动画类SlideTransitionAnimator

#import <Foundation/Foundation.h>

// 声明实现UIViewControllerAnimatedTransitioning协议
@interface SliderTransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>

//标识目标视图是否已经呈现
@property (nonatomic) BOOL isPresenting;
@end
#import "SliderTransitionAnimator.h"

@implementation SliderTransitionAnimator

- (NSTimeInterval) transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {

    return 0.5;
}

- (void)animateTransition:(id<UIViewControllerTransitioning>)transitionContext {

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerkey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerkey];

    ...

    if (self.isPresenting) {
        [transitionContext containerView addSubview:fromC.view];
        [transitionContext containerView addSubview:toVC.view];

        toVC.view.frame = transFormedStartFrame;
        [UIView animatedWithDuration:AnimationDuration
                               deley:0
                             options:UIViewAnimationOptionCurveEaseOut
                          animations:^{
            toVC.view.frame = transformedEndFrame;
        } completion:^(BOOL finished){
            [transitionContext completeTransition:YES];
        }];
    } else {

        [transitionContext containerView addSubview:toVC.view];
        [transitionContext.containerView addSubview:fromVC.view];

        [UIView animateWithDuration:AnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            fromVC.view.frame = transformedStartFrame;
        } completion:^(BOOL finished){
            [transitionContext completeTransition:YES];
        }];

    }
}
@end

具体使用是在视图控制器中实现UINavigationControllerDelegate协议中的navigationController:animationControllerForOperation:fromViewController:toViewController:方法。下面是ViewController实现的部分代码:

@interface ViewController:UITableViewController<UINavigationControllerDelegate>
...
@end
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{

    id *animator = <实例化自定义的动画对象>
    // operation判定是否视图呈现
    animator.presenting = (operation == UINavigationControllerOperationPop)?NO:YES;
    return animator;
}

@end

4.2.2 模态导航自定义过渡动画

模态导航自定义过渡动画需要在视图控制器中实现UIViewControllerTransitioningDelegate协议,该协议定义的方法。

animationControllerForPresentedController:presentingController:sourceController:,在呈现视图时候调用

a nimationControllerForDissForDismissedController:,在关闭视图时候调用

这两个方法的返回值都是实现UIViewControllerAnimatedTransitioning协议的自定义过渡动画

下面是ViewController实现的部分代码

@interface ViewController : UITableViewController<UIViewControllerTransitioningDelegate>
...
@end
@implementation ViewController
...
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    id transitioning = <实例化自定义的动画对象>;
    return transitioning;
}

- (id<UIViewControllerAnimatedTransitioning>)animatinControllerForDismissedController:(UIViewController *)dismissed
{
    id transitioning = <实例化自定义的动画对象>;
    return transitioning;
}
@end

4.2.3 实例:使用HUAnimator自定义过渡动画框架

https://github.com/cinkster/HUAnimator 下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值