原文:https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html

代码:https://github.com/xufeng79x/ViewBaseAnimation

1.简介

  Animation,源于拉丁语,意为给无生命的物体注入灵魂。

  动画可以为app应用增色不少,提高用户体验。

  我们一般使用UIKit框架的UIView自带的动画功能就可以满足大部分场景。但是如果要实现layer层的动画则需要使用Core Animation框架了。本文我们着重学习         UIView的自带动画功能。

2.可动画参数

  在UIView中并不是所有的属性变化都可以转换成动画。只有下表中7个属性具有动画资格。

  

Property

Changes you can make

frame

Modify this property to change the view’s size and position relative to its superview’s coordinate system. (If the transformproperty does not contain the identity transform, modify the bounds or center properties instead.)

bounds

Modify this property to change the view’s size.

center

Modify this property to change the view’s position relative to its superview’s coordinate system.

transform

Modify this property to scale, rotate, or translate the view relative to its center point. Transformations using this property are always performed in 2D space. (To perform 3D transformations, you must animate the view’s layer object using Core Animation.)

alpha

Modify this property to gradually change the transparency of the view.

backgroundColor

Modify this property to change the view’s background color.

contentStretch

Modify this property to change the way the view’s contents are stretched to fill the available space.




Animating Property Changes in a View

单个view的动画效果






1.触发动画

  如果我们单纯的改变以上的参数并不会产生任何动画效果,或者理解为并不会产生变化前到变换后的“慢动作”效果。在iOS4以及之后的版本中我们通常使用如下UIView的类方法进行基于block的动画驱动:

以上方法都是类方法,所以我们可以在一个block进行多个view的参数修改已达到多个view同时产生动画的效果。

如下我们先来实现一个简单的透明度的效果:

-(void)simpleAnimation
{
    [UIView animateWithDuration:2.0 animations:^{
        self.blueView.alpha = 0.0;
        self.redView.alpha = 0.0;
    }];

}

上述代码中将在2秒内缓慢的将两个view的透明度将为0,既不可见。

结果:

  

  上述例子中我们仅仅使用最简单的类方法实现了动画,如果想要实现更多的效果则我们需要使用如下方法

  animateWithDuration:delay:options:animations:completion:

  上述方法能够代码如下效果:

  • The delay to use before starting the animation
  • 动画延迟执行
  • The type of timing curve to use during the animation

  • 动画可以以多种方式执行
  • The number of times the animation should repeat

  • 指定动画执行的重复次数
  • Whether the animation should reverse itself automatically when it reaches the end

  • 动画自动回放功能
  • Whether touch events are delivered to views while the animations are in progress

  • 动画执行
  • Whether the animation should interrupt any in-progress animations or wait until those are complete before starting

以下为此方法的详细参数说明

duration

The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them.

动画总共持续时间,单位为秒。如果你传入负数或者0的时候将不会产生动画效果

delay

The amount of time (measured in seconds) to wait before beginning the animations. Specify a value of 0 to begin the animations immediately.

动画执行延迟时间,单位为秒,如果你传入0,则动画将立即执行。

options

A mask of options indicating how you want to perform the animations. For a list of valid constants, see UIViewAnimationOptions.

动画执行选项。可参考UIViewAnimationOptions. 以下为所有可选选项,定义动画的执行特点和变化规律等丰富选择。

enum {
   UIViewAnimationOptionLayoutSubviews            =  <<  ,
   UIViewAnimationOptionAllowUserInteraction      =  <<  ,
   UIViewAnimationOptionBeginFromCurrentState     =  <<  ,
   UIViewAnimationOptionRepeat                    =  <<  ,
   UIViewAnimationOptionAutoreverse               =  <<  ,
   UIViewAnimationOptionOverrideInheritedDuration =  <<  ,
   UIViewAnimationOptionOverrideInheritedCurve    =  <<  ,
   UIViewAnimationOptionAllowAnimatedContent      =  <<  ,
   UIViewAnimationOptionShowHideTransitionViews   =  <<  ,
   UIViewAnimationOptionOverrideInheritedOptions  =  <<  ,

   UIViewAnimationOptionCurveEaseInOut            =  << ,
   UIViewAnimationOptionCurveEaseIn               =  << ,
   UIViewAnimationOptionCurveEaseOut              =  << ,
   UIViewAnimationOptionCurveLinear               =  << ,

   UIViewAnimationOptionTransitionNone            =  << ,
   UIViewAnimationOptionTransitionFlipFromLeft    =  << ,
   UIViewAnimationOptionTransitionFlipFromRight   =  << ,
   UIViewAnimationOptionTransitionCurlUp          =  << ,
   UIViewAnimationOptionTransitionCurlDown        =  << ,
   UIViewAnimationOptionTransitionCrossDissolve   =  << ,
   UIViewAnimationOptionTransitionFlipFromTop     =  << ,
   UIViewAnimationOptionTransitionFlipFromBottom  =  << ,
};
typedef NSUInteger UIViewAnimationOptions;
animations

A block object containing the changes to commit to the views. This is where you programmatically change any animatable properties of the views in your view hierarchy. This block takes no parameters and has no return value. This parameter must not beNULL.

block对象,其内容即为动画内容。此block无参数,无返回值不能为null

completion

A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL.

block对象,当动画执行完毕的时候会调用此block。没有返回值,有一个布尔类型的参数用于监控当前动画是否已经执行完毕。如果duration参数为0的时候,此block将会在下一次runloop的周期开始时候出发。此参数可谓nil,以为不需要事后处理任何东西。

上述例子中的我们使用animateWithDuration:animations:方法来实现了动画,其实内部依然是调用了animateWithDuration:delay:options:animations:completion:只是有些参数使用了默认值而已。如下面的代码等价于上述例子:

-(void)simpleAnimation
{
//    [UIView animateWithDuration:2.0 animations:^{
//        self.blueView.alpha = 0.0;
//        self.redView.alpha = 0.0;
//    }];

    [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{
        self.blueView.alpha = 0.0;
        self.redView.alpha = 0.0;
    } completion:nil];

}

2.高级-动画block的嵌套

  我们可以在一个动画的block中启动另外一个动画如

-(void) nestAnimationDefault
{
    [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{
        self.blueView.alpha = 0.0;

        [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{
            self.redView.alpha = 0.0;
        } completion:nil];

    } completion:nil];

}

结果:

你可能已经注意到,在嵌套代码中红色view的动画被指定为持续5秒,但是在结果中却依然和蓝色view持续一样的时间。

原因为嵌套动画的参数要继承其父动画的参数,当然我们也可以在嵌套动画中覆盖重写自己的参数,但是需要在选项参数中指定UIViewAnimationOptionOverrideInheritedCurve 和 UIViewAnimationOptionOverrideInheritedDuration

上述代码修改为:

-(void) nestAnimationDefault
{
    [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{
        self.blueView.alpha = 0.0;

        [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone|UIViewAnimationOptionOverrideInheritedCurve | UIViewAnimationOptionOverrideInheritedDuration animations:^{
            self.redView.alpha = 0.0;
        } completion:nil];

    } completion:nil];

}

结果:

            

3.高级-动画重复

  有时候我们需要某个动画按照指定的变化重复多次,如何做呢?

-(void)repeatAnimation
{
    [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{
        [UIView setAnimationRepeatCount:];
        self.blueView.alpha = 0.0;
        self.redView.alpha = 0.0;
    } completion:nil];
}

上述动画中通过setAnimationRepeatCount:方法设定了当前动画被执行3此,需要注意的是此方法只影响当前动画。

结果:

            

4.高级-动画反转变化

  类似呼吸的效果,一吐一吸。需要指定UIViewAnimationOptionAutoreverse选项。

-(void)reverseAnimation
{
    [UIView animateWithDuration: options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone |UIViewAnimationOptionAutoreverse animations:^{
        [UIView setAnimationRepeatCount:3.0];
        self.blueView.alpha = 0.0;
        self.redView.alpha = 0.0;
    } completion:nil];
}

结果:

          

我们可以看到view从有到无一共发生4次,最有一次突然间消失,为什么会发生4次,最后一次为什么会突然消失呢?

这是因为原本一次的动画当执行为反转动画的时候,一次即代表【有到无】和【无到有】算一次,既【有到无】为0.5次,【无到有】为0.5次。

所以当repeat指定为三次的时候最后一次为【无到有】,但是按照block的参数变化指定来说需要将其变为【无】,所以最后一次就突然的消失了以遵守这个约束。

所以要想顺畅的让其变化三次并顺滑的过渡到参数变化的约束值,repeat需要为[X.5],此例子中我们可以将repeat指定为2.5次。

[UIView setAnimationRepeatCount:2.5];

最终的效果为:

          



Creating Animated Transitions Between Views

多个view之间的过度动画效果






当你在view层级中增加,删除,隐藏和显示某个view的时候使用过度动画效果使得这种变化更加顺滑。使用view级别的过度动画时你可以实现以下两种效果:

就如一个view钟只能有7个参数具可动画效果,在此场景中也只有上述红色标出的动作具有专场动画效果。

  • 改变view的子view。
  • 在view层级中替换某个view

对于多个view之间的关联过度动画可以使用如下类方法进行操作:

transitionWithView:duration:options:animations:completion:

+ (void)transitionWithView:(UIView *)view
                  duration:(NSTimeInterval)duration
                   options:(UIViewAnimationOptions)options
                animations:(void (^)(void))animations
                completion:(void (^)(BOOL finished))completion

Parameters

view

The container view that performs the transition.

发生动画的效果的view,通常选取参与变化的view的共有父view作为此参数值。

duration

The duration of the transition animation, measured in seconds. If you specify a negative value or 0, the transition is made without animations.

过度动画持续时间,单位为秒。如果指定为负值或者0的时候,将不会产生动画效果。

options

A mask of options indicating how you want to perform the animations. For a list of valid constants, see UIViewAnimationOptions.

过度动画的选项指定,可以参考 UIViewAnimationOptions.

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    UIViewAnimationOptionLayoutSubviews            =  <<  ,
    UIViewAnimationOptionAllowUserInteraction      =  <<  , // turn on user interaction while animating
    UIViewAnimationOptionBeginFromCurrentState     =  <<  , // start all views from current value, not initial value
    UIViewAnimationOptionRepeat                    =  <<  , // repeat animation indefinitely
    UIViewAnimationOptionAutoreverse               =  <<  , // if repeat, run animation back and forth
    UIViewAnimationOptionOverrideInheritedDuration =  <<  , // ignore nested duration
    UIViewAnimationOptionOverrideInheritedCurve    =  <<  , // ignore nested curve
    UIViewAnimationOptionAllowAnimatedContent      =  <<  , // animate contents (applies to transitions only)
    UIViewAnimationOptionShowHideTransitionViews   =  <<  , // flip to/from hidden state instead of adding/removing
    UIViewAnimationOptionOverrideInheritedOptions  =  <<  , // do not inherit any options or animation type

    UIViewAnimationOptionCurveEaseInOut            =  << , // default
    UIViewAnimationOptionCurveEaseIn               =  << ,
    UIViewAnimationOptionCurveEaseOut              =  << ,
    UIViewAnimationOptionCurveLinear               =  << ,

    UIViewAnimationOptionTransitionNone            =  << , // default
    UIViewAnimationOptionTransitionFlipFromLeft    =  << ,
    UIViewAnimationOptionTransitionFlipFromRight   =  << ,
    UIViewAnimationOptionTransitionCurlUp          =  << ,
    UIViewAnimationOptionTransitionCurlDown        =  << ,
    UIViewAnimationOptionTransitionCrossDissolve   =  << ,
    UIViewAnimationOptionTransitionFlipFromTop     =  << ,
    UIViewAnimationOptionTransitionFlipFromBottom  =  << ,
} NS_ENUM_AVAILABLE_IOS(4_0);
animations

A block object that contains the changes you want to make to the specified view. This block takes no parameters and has no return value. This parameter must not be NULL.

block对象,内容为过度动画。无参数无返回值,但是不能为NULL。

completion

A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL.

block对象,让过度动画结束的时候会执行这个block。有一个布尔类型的参数用于监控过度动画是否结束。如果duration被指定为0,这个block将会在下一次的runloop周期中被执行,此参数可以为NULL。

1.例子-改变view的子view

代码:

- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [UIView transitionWithView:self.containerView
                      duration:1.0
                       options:UIViewAnimationOptionTransitionCurlUp
                    animations:^{
                        self.currentView.hidden = YES;
                        self.swapView.hidden = NO;

               self.swapView.alpha = 0.0;
                    }
                    completion:^(BOOL finished){
                        UIView*    temp = self.currentView;
                        self.currentView = self.swapView;
                        self.swapView = temp;              

self.currentView.alpha = 1.0;

                    }];
}

上述代码中我们在一个名为containerView上的两个子view做影藏和显示的替换效果。

结果:
                                         

上述代码实现基于self.view的过度动画,但是如下这个效果并没有实现,按照代码应该在专场过程中,当前的view会附件透明。

self.swapView.alpha = 0.0;

原因为上述动画在实际实现过程中,只是内部生成了两个快照图片,在发生过度动画期间只是在这两个图片之间切换而已。

如果我们要在过度动画进行中实现内部内容的动画效果需要加上 UIViewAnimationOptionAllowAnimatedContent操作选项。

加上后的效果为:

2.例子--在view层级中替换某个view

View的替换可以快速的controller的不变的情况下动态更改view层级,从而实现不同的界面展现。

通常我们使用如下方法进行这一个操作,

transitionFromView:toView:duration:options:completion:

+ (void)transitionFromView:(UIView *)fromView
                    toView:(UIView *)toView
                  duration:(NSTimeInterval)duration
                   options:(UIViewAnimationOptions)options
                completion:(void (^)(BOOL finished))completion

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [UIView transitionFromView:(self.displayingPrimary ? self.primaryView : self.secondaryView)
                        toView:(self.displayingPrimary ? self.secondaryView : self.primaryView)
                      duration:1.0
                       options:(self.displayingPrimary ? UIViewAnimationOptionTransitionFlipFromRight :
                                UIViewAnimationOptionTransitionFlipFromLeft)
                    completion:^(BOOL finished) {
                        if (finished) {
                            self.displayingPrimary = !self.displayingPrimary;
                        }
                    }];
}

上述代码中我们事先了两个view以从左从右过度的笑话效果,将一个view移除后将另外一个view显示出来。

结果:

                                             

上述例子中档点击屏幕替换view后发现最后为空白屏幕,这是应为此方法将会移除fromView并使用toView来代替他,如果你想保持对fromView的引用,你需要自己去维护,因为默认情况下框架会直接将此view进行删除(或者引用计数减一,不维护则会被回收)。

如果你仅仅想要隐藏fromView的话你也可以将UIViewAnimationOptionShowHideTransitionViews最为一个选项。

加上此选项后的结果为:

                                                     



Linking Multiple Animations Together

连接多个动画






我们可以使用 animateWithDuration:animations:completion: 和 animateWithDuration:delay:options:animations:completion:的completion handler来将两个动画相连使得他们能够有序而非同时进行。

当让我们也可以使用动画嵌套的方式,将delay控制成有先后顺序去执行也可以达到相同效果,你可以两者选一。



Animating View and Layer Changes Together

将基于view的动画和layer层的动画嵌套使用





略。

  

[New learn]动画-基于UIView的更多相关文章

  1. 核心动画与UIView的区别

    核心动画与UIView的区别 1.核心动画只作用于layer,使用核心动画之前,必须有layer 2.核心动画只是假象,并没有移动实际位置 什么时候使用核心动画,什么时候使用UIView动画 1.当不 ...

  2. 核心动画和UIView动画的区别

    核心动画和UIView动画的区别 1.核心动画制作用在Layer 2.核心动画的修改的属性都是假象,他的真实位置没有发生变化()

  3. iOS&nbsp;动画总结—UIView动画

    1.概述 UIKit直接将动画集成到UIView类中,实现简单动画的创建过程.UIView类定义了几个内在支持动画的属性声明,当这些属性发生改变时,视图为其变化过程提供内建的动画支持. 执行动画所需要 ...

  4. iOS动画-从UIView到Core Animation

    首先,介绍一下UIView相关的动画. UIView普通动画: [UIView beginAnimations: context:]; [UIView commitAnimations]; 动画属性设 ...

  5. iOS动画1 — UIView动画

    iOS动画基础是Core Animation核心动画.Core Animation是iOS平台上负责图形渲染与动画的基础设施.由于核心动画的实现比较复杂,苹果提供了实现简单动画的接口—UIView动画 ...

  6. Swift下的基于UIView的位置属性扩展

    一个比较简单能满足大部分需求的extensin,如下: swift 的基于UIView的位置属性 包含: 上下左右:left.right.top.botom 高宽:height.width 中心点:c ...

  7. IOS启动页动画(uiview 淡入淡出效果 )2

    Appdelegate里面右个这个函数,只要它没结束,你的等待界面就不会消失.以在启动的时候做些动画 - (BOOL)application:(UIApplication *)application ...

  8. 转-iOS 动画总结----UIView动画

    来自:http://blog.csdn.net/huifeidexin_1/article/details/7597868/ 1.概述 UIKit直接将动画集成到UIView类中,实现简单动画的创建过 ...

  9. iOS核心动画以及UIView动画的介绍

    我们看到很多App带有绚丽狂拽的特效,别出心裁的控件设计,很大程度上提高了用户体验,在增加了实用性的同时,也赋予了app无限的生命力.这些华丽的效果很多都是基于iOS的核心动画原理实现的,本文介绍一些 ...

随机推荐

  1. 具体数学二项式至生成函数章-----致敬Kunth

    关于标题取得这么奇怪.因为在具体数学中.这两章是分开叙述的.并且分别叙述得淋漓尽致! 我只参悟其中关于生成函数的一小部分内容(暂时于我够用了.) 提二项式系数之前不得不提组合数.以往在高中用的是符号C ...

  2. I/O复用----poll

    2018-08-01 (星期三)poll(): #include <sys/poll.h> int poll (struct pollfd *fd, unsigned int nfds, ...

  3. axios请求,拦截器的使用

    1. axios 创建请求 import axios from 'axios' import {Message} from 'element-ui' import router from " ...

  4. 洛谷4245:【模板】任意模数NTT——题解

    https://www.luogu.org/problemnew/show/P4245 给两个多项式,求其乘积,每个系数对p取模. 参考: 代码与部分理解参考https://www.luogu.org ...

  5. LOJ6368:请让本题永远沉睡于此——题解

    https://loj.ac/problem/6368 给一个分数,求对p=1e9+7取模的值. 给高一同学出的毒瘤模拟题,正好试试给loj传题,竟然过审了,虽然个人觉得很水,但是考试情况来看仅有一人 ...

  6. BZOJ Lydsy5月月赛 ADG题解

    题目链接 BZOJ5月月赛 题解 好弱啊QAQ只写出三题 A 判断多干个数乘积是否是某个数的倍数有很多方法,比较常用的是取模,但这里并不适用,因为模数不定 会发现数都比较小,所以我们可以考虑分解质因子 ...

  7. MySQL基础原创笔记(二)

    表索引关键字:PRI primary key 表示主键,唯一 写法: id bigint(20) unsigned primary key not null ,uni UNIQUE 表示唯一 id b ...

  8. 使用JavaScript OOP特性搭建Web应用

    最近,我面试了一个有五年 Web 应用程序开发经验的软件开发人员.四年半来她一直在从事 JavaScript 相关的工作,她自认为 JavaScript 技能非常好,但在不久之后我就发现实际上她对 J ...

  9. stout代码分析之四:Try类

    stout的在异常捕获上遵循于谷歌类似的原则,不适用try...catch...,而是从函数返回值判断异常.Try类正是实现了这样的一个功能. 同Option一样,Try是一个模板类,每个类对象都有两 ...

  10. Activiti工作流——流程表数据转化

    任务流程部署:  启动流程实例: 请假人完成请假申请: 部门经理完成审批: 总经理审批完成: