快捷搜索:
您的位置:奥门新萄京8522 > 动漫动画 > 庆父不死,Android补间动画

庆父不死,Android补间动画

2019-09-30 20:39

虹蓝,小福贵可以说是开启了国产动画的新时代。那个时候我还在上小学,国产有这种神作霸屏,进口动画有犬夜叉柯南,动画行业算得上是百花齐放了。如果当时以这种势头下去,国产动画成为中国的文化一大招牌只是时间的问题。我们有五千年的历史,诗词,美食,武侠,音乐…这些题材算是取之不尽 用之不竭。可惜,短短三五年,市场上充斥起了喜羊羊,光头强…能说什么,哀其不幸怒其不争罢了。

android中补间动画分为透明动画,旋转动画,缩放动画和位移移动,动画可以作用在所有的view上,动画可以单独使用,也可以多个动画一起使用。

在开始学习Core Animation提供的layer的隐式动画和layer的显式动画之前,我们先来总结一下UIView block动画,因为:

版本记录

版本号 时间
V1.0 2017.09.24
重要写在前面

android动画中所有涉及到坐标的地方,坐标原点都是view的左上角。

补间动画只能在视觉上改变view的状态,但是view实际上还是以原来的大小在原来的位置上。例如把一个view从左上角移动到了右下角,那个这个view其实还在左上角,只是在视觉上移动到了右下角,如果view上有点击事件,那么只有点左上角那个位置才能触发点击事件,点右下角不会有任何反应。

  • 在实际开发中我们用的最多的还是view,而不是layer,所以更多情况下如果我们要做动画的话,用的还是UIView block动画,而不是layer的隐式动画和显示动画;
  • 这里总结一下,可以方便我们在后面两篇学习layer的隐式动画和显式动画时作对比,以期加深对动画的理解。

前言

app中好的炫的动画可以让用户耳目一新,为产品增色不少,关于动画的实现我们可以用基本动画、关键帧动画、序列帧动画以及基于CoreGraphic的动画等等,接下来这几篇我就介绍下我可以想到的几种动画绘制方法。具体Demo示例已开源到Github —— 刀客传奇,感兴趣的可以看我写的另外几篇。
1. 实现动画方式深度解析(一) —— 播放GIF动画(一)
2. 实现动画方式深度解析(二) —— 播放GIF动画之框架FLAnimatedImage的使用(二)
3. 实现动画方式深度解析(三) —— 播放序列帧动画(一)
4. 实现动画方式深度解析(四) —— QuartzCore框架(一)
5. 实现动画方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)
6. 实现动画方式深度解析(六) —— Core Animation Basics(三)
7. 实现动画方式深度解析(七) —— Core Animation之Setting Up Layer Objects(四)
8. 实现动画方式深度解析(八) —— Core Animation之动画层内容 (五)
9. 实现动画方式深度解析(九) —— Core Animation之构建图层层级 (六)
10. 实现动画方式深度解析(十) —— Core Animation之高级动画技巧 (七)
11. 实现动画方式深度解析(十一) —— Core Animation之更改图层的默认行为(八)
12. 实现动画方式深度解析(十二) —— Core Animation之提高动画的性能(九)
13. 实现动画方式深度解析(十三) —— Core Animation之图层样式属性动画(十)
14. 实现动画方式深度解析(十四) —— Core Animation之 KVC 扩展(十一)
15. 实现动画方式深度解析(十五) —— Core Animation之可动画属性 (十二)
16. 实现动画方式深度解析(十六) —— Core Animation之CABasicAnimation动画示例 (十三)
17. 实现动画方式深度解析(十七) —— Core Animation之CAKeyframeAnimation动画示例 (十四)

一 用代码的方式写补间动画

UIView动画

UIView动画也是系统提供的一种动画实现方式,这种方式是实现很简单。UIView动画可以看做是对Core Animation的封装。

UIView可以进行动画属性如下:

  • frame
  • bounds
  • center
  • transform
  • alpha
  • backgroundColor
  • contentStretch

下面我们看一下UIView提供了有关动画的接口。

@interface UIView(UIViewAnimation)

  (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;  // additional context info passed to will start/did stop selectors. begin/commit can be nested
  (void)commitAnimations;                                                 // starts up any animations when the top level animation is commited

// no getters. if called outside animation block, these setters have no effect.
  (void)setAnimationDelegate:(nullable id)delegate;                          // default = nil
  (void)setAnimationWillStartSelector:(nullable SEL)selector;                // default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context
  (void)setAnimationDidStopSelector:(nullable SEL)selector;                  // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
  (void)setAnimationDuration:(NSTimeInterval)duration;              // default = 0.2
  (void)setAnimationDelay:(NSTimeInterval)delay;                    // default = 0.0
  (void)setAnimationStartDate:(NSDate *)startDate;                  // default = now ([NSDate date])
  (void)setAnimationCurve:(UIViewAnimationCurve)curve;              // default = UIViewAnimationCurveEaseInOut
  (void)setAnimationRepeatCount:(float)repeatCount;                 // default = 0.0.  May be fractional
  (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;    // default = NO. used if repeat count is non-zero
  (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;  // default = NO. If YES, the current view position is always used for new animations -- allowing animations to "pile up" on each other. Otherwise, the last end state is used for the animation (the default).

  (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;  // current limitation - only one per begin/commit block

  (void)setAnimationsEnabled:(BOOL)enabled;                         // ignore any attribute changes while set.
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
  (BOOL)areAnimationsEnabled;
#endif
  (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);

#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
  (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif

@end


@interface UIView(UIViewAnimationWithBlocks)

  (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);

  (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0

  (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL

/* Performs `animations` using a timing curve described by the motion of a spring. When `dampingRatio` is 1, the animation will smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will oscillate more and more before coming to a complete stop. You can use the initial spring velocity to specify how fast the object at the end of the simulated spring was moving before it was attached. It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a second. So if you're changing an object's position by 200pt in this animation, and you want the animation to behave as if the object was moving at 100pt/s before the animation started, you'd pass 0.5. You'll typically want to pass 0 for the velocity. */ 
  (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

  (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

  (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview

/* Performs the requested system-provided animation on one or more views. Specify addtional animations in the parallelAnimations block. These additional animations will run alongside the system animation with the same timing and duration that the system animation defines/inherits. Additional animations should not modify properties of the view on which the system animation is being performed. Not all system animations honor all available options.
 */
  (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end


@interface UIView (UIViewKeyframeAnimations)

  (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
  (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation

@end

所有动画的公共属性

这里列出所有动画都有的方法,包括四种动画以及AnimationSet,这些动画的合集

//设置动画的持续时间
alphaAnimation.setDuration(2000);
 //设置动画播放完毕后是否保持在动画播放完毕的状态
alphaAnimation.setFillAfter(true);
/*
设置动画的重复次数,这里的重复次数指的是动画第一次播放完毕后还会重复播放几次,这里设置为3,就是动画一共播放四次,开始执行一次动画,然后再重复执行三次。
 */
alphaAnimation.setRepeatCount(3);
/*
设置动画重复的模式
有Animation.RESTART:在动画多次播放时每一次都和第一次一样,重复执行
 Animation.REVERSE:每一次执行动画是,和上一次执行相反的操作
例如动画是把view放大到原来的两倍,动画一共执行4次
如果是Animation.RESTART,就会每次都从view本身的大小变到2倍的大小,这一过程一共执行4次
如果是Animation.REVERSE,则第一回从本身大小到2倍,第二回从2倍到本身大小,第三回从2倍到view本身第四回再从view本身到2倍
*/
 alphaAnimation.setRepeatMode(Animation.REVERSE);

用透明动画举例

目录

UIView 动画几个重要接口

下面我们就看一下几个重要的接口。

单独使用动画

1 AlphaAnimation
AlphaAnimation是透明动画,可以改变view的透明度
1.1 创建动画

//创建动画,并设置起止透明度,传入的数据是浮点型,需要加f
//参数范围从0到1,0表示完全透明,1表示完全不透明
//第一个参数为开始的时候的透明度,第二个参数为结束的时候的透明度
AlphaAnimation alphaAnimation=new AlphaAnimation(1.0f,0);
alphaAnimation.setDuration(2000);
alphaAnimation.setRepeatCount(3);
alphaAnimation.setRepeatMode(Animation.REVERSE);

1.2 执行动画
首先找到需要执行动画的view,然后调用startAnimation方法,并传入需要执行的动画

imageView.startAnimation(alphaAnimation);

2 ScaleAnimation
缩放动画,控制view的缩放
2.1 创建动画

 /*传入8个参数
前4个参数分别为:
开始长度的缩放比例,终止长度的缩放比例,其实宽度的缩放比例,终止宽度的缩放比例
这四个参数都是浮点型的,代表和原view相比放大或者缩小的比例,1.0代表不变,2.0代表放大到原来的2被,0.5则代表缩小到原来的0.5倍
后四个参数设置缩放的中心点。分别为:
x轴的模式,x轴中心点的位置,y轴的模式,y轴中心点的位置
模式有三种
Animation.RELATIVE_TO_SELF:相对于自己
Animation.RELATIVE_TO_PARENT:相对于父元素
Animation.ABSOLUTE:绝对距离
如果是前两种模式,后面传入的参数代表时父元素或者自己的几倍
例如下面这种写法,代表相对于自己,大小是自己长宽的0.5倍,那么中心点x轴坐标就在空间长度一半的位置
y轴坐标也在控件一半的位置,(android动画中坐标原点都在执行该动画的view的左上角),那个中心点就是该元素的中心。
相对于父元素的也是如此,这两种x,y的坐标是相对的view乘以相应的比例得到的
如果是第三种模式,那个传入的参数谁也不相对,传入的参数是多少,坐标就是多少,坐标原点永远是view的左上角
*/
ScaleAnimation scaleAnimation=new ScaleAnimation(1.0f,2.0f,1.0f,2.0f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

可以再设置一些其他需要的参数
2.2 执行动画
执行动画都是一样的操作
3 RotateAnimation
旋转动画,控制view的旋转操作
3.1 创建动画

/*
传入6个参数,前2个参数是开始时旋转的角度,和结束时旋转的角度
正数代表顺时针,负数代表逆时针
后四个参数为设置旋转的中心点,和ScaleAnimation设置中心点一致
*/
RotateAnimation rotateAnimation=new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

可以设置一些其他的参数
3.2 执行动画
执行动画都是一样的
4 TranslateAnimation
位移动画,控制view的移动
4.1 创建动画

/*
传入8个参数
一共四组,分别为
起始时view的左上角x轴坐标
结束时view的左上角x坐标
起始时view的左上角y坐标
结束时view的左上角y坐标
view左上角坐标默认为(0,0)
每一组是一个模式加一个值组成的,模式和值进行计算得出实际的坐标值
有关模式的可以看ScaleAnimation中的讲解
 */
TranslateAnimation translateAnimation=new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0.5f);

可以设置一些其他的参数
4.2 执行动画

一、UIView可动画属性列表

1. 动画开始

  (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;  
// additional context info passed to will start/did stop selectors. begin/commit can be nested
动画合集

5 AnimationSet
动画的合集,使用它可以控制前面列出的四种动画中的一种或者多种一起执行
5.1 创建AnimationSet

//传入一个boolean类型的参数,这个参数控制的是动画执行时是匀速执行还是不匀速执行
//这个参数不好用,直接都传入true,让他匀速执行就可以
 AnimationSet animationSet=new AnimationSet(true);

5.2 将动画加入到AnimationSet中

animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);

5.3 可以设置一些参数,如果在set中设置参数,就会对set中所有的动画起作用,每个动画自己设置的参数只对自己起作用

animationSet.setDuration(2000);

5.4 执行动画

imageView.startAnimation(animationSet);

二、什么是UIView block动画?

2. 结束动画标记

  (void)commitAnimations; 
二 用xml的方式定义补间动画

用代码定义的动画都可以用xml的方式实现
首先在res目录下建立一个anim目录
再在anim目录下建立一个动画文件,在此动画文件中开始写xml

1、UIView block动画的定义、本质及能做什么动画

3. 设置动画时间

  (void)setAnimationDuration:(NSTimeInterval)duration; 
同样先说所有动画的公共属性

不用多说,和上面完全一致,需要说一点,有时这些属性没有代码提示,直接手打出来就行。

android:duration="2000"
android:repeatMode="restart"
android:repeatCount="3"
android:fillAfter="true"

1 透明动画
1.1 在xml文件中写动画

<!--需要说明的有两个参数
 fromAlpha,toAlpha,分别代表开始的透明度和结束的透明度,大小从0到1
在xml中浮点型不用加f
-->
<alpha
android:fromAlpha="1"
android:toAlpha="0"
android:duration="2000"
android:repeatMode="restart"
android:repeatCount="3"
android:fillAfter="true"/>

1.2 执行动画

//用AnimationUtils工具类把动画加载进行,传入两个参数,一个上下文,一个动画资源的id
AlphaAnimation animation=AnimationUtils.loadAnimation(this,R.anim.animation);
//执行动画
imageView.startAnimation(animationSet);

2 缩放动画
2.1 创建动画

 <!--
    fromXScale:开始时长度的大小,参数代表这个长度和view自身长度的比例,即这个长度是view自身长度的几倍
    toXScale:结束是长度的大小
    fromYScale:开始时宽度的大小
    toYScale:结束是宽度的大小
    pivotX:旋转中心点横坐标,可以传入三种类型的参数,
    50%,代表横坐标view自身的长度的50%
    50%p,代表横坐标是父元素控件的50%
    50,代表横坐标就是50。
    坐标原点是view的左上角坐标
    pivotY:旋转中心点纵坐标
    同pivotX
    -->
    <scale
        android:fromXScale="1"
        android:toXScale="2"
        android:fromYScale="1"
        android:toYScale="2"
        android:pivotX="50%"
        android:pivotY="50%"/>

2.2 执行动画
加载动画,执行动画
3 旋转动画
3.1 创建动画

 <!--
    fromDegrees:开始角度
    toDegrees:结束角度
    pivotX,pivotY:设置旋转中心点,和scale中的一样
    -->
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"/>

3.2 执行动画
加载动画,并执行动画
4 位移动画
4.1 创建动画

 <!--
    fromXDelta:动画开始时view左上角x坐标的位置
    toXDelta:动画结束时view左上角x坐标的位置
    fromYDelta:动画开始时view左上角坐标的位置
    toYDelta:动画结束时view左上角y坐标的位置
    这四个参数都可以传入
    50%,代表横坐标view自身的长度的50%
    50%p,代表横坐标是父元素控件的50%
    50,代表横坐标就是50。
    坐标原点是原始view的左上角坐标
    -->
    <translate
        android:fromXDelta="0"
        android:toXDelta="0"
        android:fromYDelta="0"
        android:toYDelta="50%"/>

4.2 执行动画
加载动画,执行动画

2、UIView block动画的分类

4. 设置动画代理

  (void)setAnimationDelegate:(nullable id)delegate;
动画合集

5 set 动画的合集
此时根元素是set元素,set元素中可以写入多个动画
set可以设置属性,set中的属性所有动画共享,动画内部的属性只有该动画自己可以使用
5.1 创建动画

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000">
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration="2000"
        android:repeatMode="restart"
        android:repeatCount="3"
        android:fillAfter="true"/>
    <translate
        android:fromXDelta="0"
        android:toXDelta="0"
        android:fromYDelta="0"
        android:toYDelta="50%"/>
    <scale
        android:fromXScale="1"
        android:toXScale="2"
        android:fromYScale="1"
        android:toYScale="2"
        android:pivotX="50%"
        android:pivotY="50%"/>
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"/>
</set>

5.2 执行动画

 AnimationSet set= (AnimationSet) AnimationUtils.loadAnimation(this,R.anim.animation);
imageView.startAnimation(set);
(1)UIView block基础动画(UIView block属性动画的一种)

5. 设置动画将开始时代理对象执行的SEL

  (void)setAnimationWillStartSelector:(nullable SEL)selector; 
①什么是UIView block基础动画?

6. 设置动画结束时代理对象执行的SEL

  (void)setAnimationDidStopSelector:(nullable SEL)selector; 
②如何使用UIView block基础动画?

7. 设置动画延迟执行的时间

  (void)setAnimationDelay:(NSTimeInterval)delay;  
(2)UIView block关键帧动画(UIView block属性动画的一种)

8. 设置动画的重复次数

  (void)setAnimationRepeatCount:(float)repeatCount; 
①什么是UIView block关键帧动画?

9. 设置动画的曲线

  (void)setAnimationCurve:(UIViewAnimationCurve)curve; 

这里有一个枚举值,如下所示:

typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
    UIViewAnimationCurveEaseInOut,         // slow at beginning and end
    UIViewAnimationCurveEaseIn,            // slow at beginning
    UIViewAnimationCurveEaseOut,           // slow at end
    UIViewAnimationCurveLinear,
};
②如何使用UIView block关键帧动画?

10. 设置是否从当前状态开始播放动画

  (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; 

 // default = NO. If YES, the current view position is always used for new animations -- allowing animations to "pile up" on each other. Otherwise, the last end state is used for the animation (the default).

假设上一个动画正在播放,且尚未播放完毕,我们将要进行一个新的动画:

  • 当为YES时:动画将从上一个动画所在的状态开始播放
  • 当为NO时:动画将从上一个动画所指定的最终状态开始播放(此时上一个动画马上结束)。
(3)UIView block过渡动画

11. 设置动画是否继续执行相反的动画

  (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;   

 // default = NO. used if repeat count is non-zero
①什么是UIView block过渡动画?

12. 是否禁用动画效果

对象属性依然会被改变,只是没有动画效果。

  (void)setAnimationsEnabled:(BOOL)enabled; 
②如何使用UIView block过渡动画?

13. 设置视图的过渡效果

  (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; 

 // current limitation - only one per begin/commit block

这里有一个枚举UIViewAnimationTransition,如下所示:

typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
};

三、如何使用UIView block动画?(应用举例)

14. block动画

有关UIView的block动画,全部在UIView的一个分类UIViewAnimationWithBlocks里面。

@interface UIView(UIViewAnimationWithBlocks)

  (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);

  (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0

  (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL

/* Performs `animations` using a timing curve described by the motion of a spring. When `dampingRatio` is 1, the animation will smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will oscillate more and more before coming to a complete stop. You can use the initial spring velocity to specify how fast the object at the end of the simulated spring was moving before it was attached. It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a second. So if you're changing an object's position by 200pt in this animation, and you want the animation to behave as if the object was moving at 100pt/s before the animation started, you'd pass 0.5. You'll typically want to pass 0 for the velocity. */ 
  (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

  (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

  (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview

/* Performs the requested system-provided animation on one or more views. Specify addtional animations in the parallelAnimations block. These additional animations will run alongside the system animation with the same timing and duration that the system animation defines/inherits. Additional animations should not modify properties of the view on which the system animation is being performed. Not all system animations honor all available options.
 */
  (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end

1、UIView block基础动画举例

UIView 动画简单示例

下面我们就看一下UIView动画实现的简单示例。

2、UIView block关键帧动画举例

1. 简单动画

我们先看一下简单的动画示例。

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIView *animationView;

@end

@implementation ViewController

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];

    //UI
    [self setupUI];

    //UIView动画
    [self demoPropertyUIViewAnimation];
}

#pragma mark - Object Private Function

- (void)demoPropertyUIViewAnimation
{
    [UIView beginAnimations:@"animation" context:nil];
    [UIView setAnimationDuration:3.0];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationWillStartSelector:@selector(startAnimation)];
    [UIView setAnimationDidStopSelector:@selector(stopAnimation)];
    [UIView setAnimationRepeatCount:10];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    self.animationView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
    [UIView commitAnimations];
}

- (void)setupUI
{
    self.view.backgroundColor = [UIColor lightGrayColor];

    self.animationView = [[UIView alloc] initWithFrame:CGRectMake(250.0, 250.0, 200.0, 200.0)];
    [self.view addSubview:self.animationView];
    self.animationView.backgroundColor = [UIColor redColor];
}

#pragma mark - Action && Notification

- (void)startAnimation
{
    NSLog(@"开始动画");
}

- (void)stopAnimation
{
    NSLog(@"停止动画");
}

@end

下面我们看一下输出以及动画效果。

2017-09-24 20:22:24.254 JJUIViewAnimation_demo9[3301:274498] 开始动画
2017-09-24 20:22:54.252 JJUIViewAnimation_demo9[3301:274498] 停止动画

图片 1

3、UIView block过渡动画举例

2. block动画

ios 4.0以后出现的block动画,这种动画也是我们工程中常用的动画形式。

  • 最简洁的Block动画:包含时间和动画
  (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); 

// delay = 0.0, options = 0, completion = NULL
  • 带有动画完成回调的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
  • 带有延迟时间和过度效果的动画
  (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);

这里有一个枚举值UIViewAnimationOptions,它就是描述过度效果的枚举值。

 UIViewAnimationOptionLayoutSubviews            //进行动画时布局子控件
 UIViewAnimationOptionAllowUserInteraction      //进行动画时允许用户交互
 UIViewAnimationOptionBeginFromCurrentState     //从当前状态开始动画
 UIViewAnimationOptionRepeat                    //无限重复执行动画
 UIViewAnimationOptionAutoreverse               //执行动画回路
 UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套动画的执行时间设置
 UIViewAnimationOptionOverrideInheritedCurve    //忽略嵌套动画的曲线设置
 UIViewAnimationOptionAllowAnimatedContent      //转场:进行动画时重绘视图
 UIViewAnimationOptionShowHideTransitionViews   //转场:移除(添加和移除图层的)动画效果
 UIViewAnimationOptionOverrideInheritedOptions  //不继承父动画设置

 UIViewAnimationOptionCurveEaseInOut            //时间曲线,慢进慢出(默认值)
 UIViewAnimationOptionCurveEaseIn               //时间曲线,慢进
 UIViewAnimationOptionCurveEaseOut              //时间曲线,慢出
 UIViewAnimationOptionCurveLinear               //时间曲线,匀速

 UIViewAnimationOptionTransitionNone            //转场,不使用动画
 UIViewAnimationOptionTransitionFlipFromLeft    //转场,从左向右旋转翻页
 UIViewAnimationOptionTransitionFlipFromRight   //转场,从右向左旋转翻页
 UIViewAnimationOptionTransitionCurlUp          //转场,下往上卷曲翻页
 UIViewAnimationOptionTransitionCurlDown        //转场,从上往下卷曲翻页
 UIViewAnimationOptionTransitionCrossDissolve   //转场,交叉消失和出现
 UIViewAnimationOptionTransitionFlipFromTop     //转场,从上向下旋转翻页
 UIViewAnimationOptionTransitionFlipFromBottom  //转场,从下向上旋转翻页

下面我们还是先看一下示例代码。

- (void)demoBlockUIViewAnimation
{
    self.animationView.frame = CGRectMake(50.0, 250.0, 200.0, 200.0);

    [UIView animateWithDuration:3.0 animations:^{
        self.animationView.backgroundColor = [UIColor blueColor];
    } completion:^(BOOL finished) {
        NSLog(@"动画完成了");
    }];
}

上面就是一个很简单的示例,非常简单,下面看一下效果。

图片 2

一、UIView可动画属性列表

最普通的属性 说明
backgroundColor --
frame 改位置和大小,一般使用transform的平移和缩放来代替
bounds 改大小,一般使用transform的缩放来代替
center 改位置,一般使用transform的平移来代替
显隐性属性 说明
hidden 注意这个属性不支持动画,最简单的可以通过alpha或背景色来代替实现
alpha --
仿射变换属性 说明
transform 可用来做view的平移、缩放、旋转动画

3. 转场动画

下面直接看代码。

- (void)demoTransitionUIViewAnimation
{
    self.animationView.frame = CGRectMake(50.0, 250.0, 200.0, 200.0);

    [UIView beginAnimations:@"Animation" context:nil];
    [UIView setAnimationDuration:3.0];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationWillStartSelector:@selector(startAnimation)];
    [UIView setAnimationDidStopSelector:@selector(stopAnimation)];
    [UIView setAnimationRepeatCount:5];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.animationView cache:YES];
    self.animationView.backgroundColor = [UIColor blueColor];
    [UIView commitAnimations];
}

转场动画有个参数cache,可以设置为YES或者NO,它们有什么区别呢?

首先把要动画的视图进行截图(此处为何要截图说明一下,因为要动画的视图上边一般都会有好多的控件,如果让动画直接操作视图,那么视图带着自身内部的控件,这样做动画的话会增加系统的负担,从而使动画效率降低,所以为了减轻系统负担,使动画更流畅,才对动画视图进行截图处理已完成动画效果),然后对视图的截图进行动画操作。

  • cache选为YES时:系统只会在动画开始的时候对视图进行截图,然后一直到动画结束,都用开始截的那张图,这种方法好处是减轻系统负担,使动画效果更流畅、更自然。但这样也必会有缺点:就是当动画视图中的控件有变化的时候,不能立即更新在视图上,从而达不到实时更新的效果。

  • cache选为NO时:系统会在动画整个过程中对视图进行实时截图,这样当视图中的控件更新时也会实时显示在动画过程中,弥补了cache选择yes得缺点,但这也把cache选择yes的优点变成缺点,是系统效率变慢,如果动画视图中的控件过多,会让动画看起来不那么自然。

这里还要注意:如果要在转换期间更改视图的外观 - 例如,从一个视图翻转到另一个视图 - 然后使用容器视图(UIView的实例),如下所示:

  • Begin an animation block.
  • Set the transition on the container view.
  • Remove the subview from the container view.
  • Add the new subview to the container view.
  • Commit the animation block.

iOS 4.0及更高版本不鼓励使用此方法。 您应该使用transition(with:duration:options:animations:completion:) 方法来执行转换。

二、什么是UIView block动画?

后记

未完,待续~~~

图片 3

1、UIView block动画的定义、本质及能做什么动画
  • 定义:UIView block动画就是用来在view层做动画的一种动画机制

  • 本质:UIView block动画的本质就是对layer的隐式动画或显式动画做了一层封装,提供简洁的Api,方便我们开发者使用。具体来说UIView block基础动画是对layer的隐式动画做了封装(因为它们同样可以设置过渡效果/图层行为,显示动画的基础动画不能设置图层行为,当然显式动画的过渡动画也可以作用于可动画属性,但是后面讲到隐式动画应该会知道UIView block基础动画是对layer的隐式动画做了封装),UIView block关键帧动画是对layer的显示动画的关键帧动画做了封装,UIView block过渡动画是对layer的显示动画的过渡动画做了封装。

  • 能做什么动画:

    • 下面我们会提到UIView block动画可分为UIView block属性动画和UIView block过渡动画,而UIView block属性动画又可分为UIView block基础动画和UIView block关键帧动画。

    • UIView block属性动画能做什么动画:那么从UIView的可动画属性列表我们可以看出,UIView block属性动画可以用来对view做背景色变化的动画、view显隐性变化的动画以及view的平移、缩放和旋转的仿射变换动画三种场景下的动画,其中执行一次UIView block基础动画只能改变一个属性值一次,执行一次UIView block关键帧动画可以设置多个关键帧所以能改变一个属性值多次

    • UIView block过渡动画能做什么动画:UIView block属性动画只能对UIView的可动画属性做动画,但是如果我们现在想要对view的非动画属性改变时(如label的文本,imageView的图片等)做动画,甚至是对view的某些行为(如view的添加和移除,两个view之间切换)做动画,那就只能使用过渡动画了。

  • 就此我们也就知道了为什么要引入UIView block动画:
    • 第一、当然就是UIView block动画是作用于view层,对layer的隐式动画或显式动画做了一层封装,提供简洁的Api,方便我们开发者使用;
    • 第二、UIView block属性动画可以帮助我们在改变view的可动画属性时能做动画效果。如果看到后面一篇隐式动画,我们会知道在改变layer的可动画属性时,即便我们什么都不做直接修改layer的属性值,这个改变的过程也会默认有一个动画,它就是隐式动画;但是当我们在改变view的可动画属性时,是没有隐式动画的,如果我们什么都不做,属性就会直接跳变到新值,所以为了达到改变view的属性时能有动画,我们就得使用UIView block动画来实现了。
    • 第三、UIView block过渡动画可以帮助我们在改变view的不可变属性或者对view做某些行为能做动画。
2、UIView block动画的分类

UIView block动画可分为UIView block属性动画和UIView block过渡动画,而UIView block属性动画又可分为UIView block基础动画和UIView block关键帧动画,接下来我们将分别介绍UIView block基础动画UIView block关键帧动画UIView block过渡动画

(1)UIView block基础动画
①什么是UIView block基础动画?

UIView block基础动画是UIView block属性动画的一种,它用来对view的可动画属性做动画,但是执行一次UIView block基础动画只能改变一个属性值一次,因为我们是一次性把属性值直接设置为目标值的(如果要想改变多次属性的值,可以在动画结束后再开始一个基础动画再改一次属性值,如此循环,但有一个更简单的办法就是使用UIView block关键帧动画,后面会说到)它主要分下面四种:

  • 最简洁的block基础动画
[UIView animateWithDuration:// 动画时长
                 animations:^{

                     // 要改变的属性
                 }];
  • 带动画完成回调的block基础动画
[UIView animateWithDuration:// 动画时长
                 animations:^{

                     // 要改变的属性
                 } completion:^(BOOL finished) {

                     // 动画完成的回调
                 }];
  • 可设置延时和自定义动画过渡效果的block基础动画
[UIView animateWithDuration:// 动画时长
                      delay:// 延时多长时间后开始执行动画
                    options:// 可自定义动画的过渡效果,来替换掉系统默认的平滑过渡效果
                 animations:^{

                     // 要改变的属性
                 } completion:^(BOOL finished) {

                     // 动画完成的回调
                 }];

UIView block基础动画自定义过渡效果(UIViewAnimationOptions)枚举值如下:

  • 一般就设置下过渡动画效果和过渡动画时间曲线就可以了;

  • 如果和后面layer显式动画的过渡动画的type和subType对比一下,会发现这里的过渡动画效果是把layer显式动画的过渡动画的type和subType组合起来了,而且这里的过渡动画效果要比layer显式动画的过渡动画的效果少得多,只有淡入淡出、正面背面二维翻转、翻页效果三种而已。

UIViewAnimationOptionTransitionNone// 过渡动画效果:不使用过渡动画
UIViewAnimationOptionTransitionCrossDissolve//过渡动画效果:淡入淡出效果,和显示动画的过渡动画的“fade”一样
UIViewAnimationOptionTransitionFlipFromTop// 过渡动画效果:正面和背面的二维翻转效果,从上向下翻转
UIViewAnimationOptionTransitionFlipFromLeft// 过渡动画效果:正面和背面的二维翻转效果,从左向右翻转
UIViewAnimationOptionTransitionFlipFromBottom// 过渡动画效果:正面和背面的二维翻转效果,从下向上翻转
UIViewAnimationOptionTransitionFlipFromRight//过渡动画效果:正面和背面的二维翻转效果,从右向左翻转
UIViewAnimationOptionTransitionCurlUp// 过渡动画效果:翻页效果,从下往上翻页
UIViewAnimationOptionTransitionCurlDown// 过渡动画效果:翻页效果,从上往下翻页

UIViewAnimationOptionCurveEaseInOut// 过渡动画的缓冲曲线:动画慢进,逐渐加快,逐渐减慢,慢出(默认值)
UIViewAnimationOptionCurveEaseIn// 过渡动画的缓冲曲线:动画慢进,逐渐加快
UIViewAnimationOptionCurveEaseOut// 过渡动画的缓冲曲线:动画逐渐减慢,慢出
UIViewAnimationOptionCurveLinear// 过渡动画的缓冲曲线:动画匀速

UIViewAnimationOptionRepeat// 重复执行动画
UIViewAnimationOptionAllowUserInteraction// 执行动画期间,开启view的用户交互

UIViewAnimationOptionAutoreverse// 执行动画回路
UIViewAnimationOptionLayoutSubviews// 执行动画时布局子控件
UIViewAnimationOptionAllowAnimatedContent// 执行动画时重绘视图
UIViewAnimationOptionBeginFromCurrentState// 从当前状态开始执行动画
UIViewAnimationOptionShowHideTransitionViews// 显示视图时显示或隐藏而不是移除或添加
UIViewAnimationOptionOverrideInheritedOptions// 不继承父动画设置
UIViewAnimationOptionOverrideInheritedCurve// 忽略嵌套动画的曲线设置
UIViewAnimationOptionOverrideInheritedDuration// 忽略嵌套动画的执行时间设置
  • Spring动画:就是指在改变属性的时候,属性值会在目标值附近摆动,类似弹簧那种的弹性动画
[UIView animateWithDuration:// 动画时长
                      delay:// 延时多长时间后开始执行动画
     usingSpringWithDamping:// 弹性效果的阻尼:范围0~1,数值越小弹性效果越明显,震得越久才能停下来
      initialSpringVelocity:// 弹性效果的初始速度:数值越大开始弹性动画时初始速度越快
                    options:// 可自定义动画的过渡效果,来替换掉系统默认的平滑过渡效果
                 animations:^{

                     // 要改变的属性
                 } completion:^(BOOL finished) {

                     // 动画完成的回调
                 }];
②如何使用UIView block基础动画?

我们只需要在UIView block基础动画的animationsblock里直接把可动画属性改变为目标值就可以了。

(2)UIView block关键帧动画
①什么是UIView block关键帧动画?

上面说到了UIView block基础动画是UIView block属性动画的一种,而此处的UIView block关键帧动画也是UIView block属性动画的一种,它也是用来对view的可动画属性做动画的,只不过效果可能在某些场景下比基础动画要方便或者丰富一些,但是执行一次UIView block关键帧动画可以设置多个关键帧所以能改变一个属性值多次,而不是一次性把属性值设置目标值

需要注意的是:UIView block关键帧动画设置关键帧只能通过增加关键帧方法来设置,相当于layer显示动画的关键帧动画的数组关键帧法,这个是不支持路径关键帧法的。

  • UIView block关键帧动画
[UIView animateKeyframesWithDuration:// 动画时长
                               delay:// 延时多长时间后开始执行动画
                             options:// 可自定义动画的过渡效果,来替换掉系统默认的平滑过渡效果
                          animations:^{

                              // 添加关键帧
                          } completion:^(BOOL finished) {

                              // 动画完成的回调
                          }];

UIView block关键帧自定义过渡效果(UIViewKeyframeAnimationOptions)枚举值如下:

  • 一般就设置下过渡动画的运算模式就可以了,或者直接采取默认就可以了。
UIViewKeyframeAnimationOptionCalculationModeLinear// 运算模式:连续,默认
UIViewKeyframeAnimationOptionCalculationModeDiscrete// 运算模式:离散
UIViewKeyframeAnimationOptionCalculationModePaced// 运算模式:均匀执行
UIViewKeyframeAnimationOptionCalculationModeCubic// 运算模式:平滑
UIViewKeyframeAnimationOptionCalculationModeCubicPaced// 运算模式:平滑均匀

UIViewKeyframeAnimationOptionRepeat = UIViewAnimationOptionRepeat// 重复执行动画
UIViewKeyframeAnimationOptionAllowUserInteraction = UIViewAnimationOptionAllowUserInteraction// 执行动画期间,开启view的用户交互

UIViewKeyframeAnimationOptionAutoreverse = UIViewAnimationOptionAutoreverse// 执行动画回路
UIViewKeyframeAnimationOptionLayoutSubviews = UIViewAnimationOptionLayoutSubviews// 执行动画时布局子控件
UIViewKeyframeAnimationOptionBeginFromCurrentState = UIViewAnimationOptionBeginFromCurrentState// 从当前状态开始执行动画
UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions// 不继承父动画设置
UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration// 忽略嵌套动画的执行时间设置
  • 增加关键帧的方法
[UIView addKeyframeWithRelativeStartTime:// 这一帧动画开始的时间点(占总时间的比例)
                        relativeDuration:// 这一帧动画的动画时长(占总时间的比例)
                              animations:^{

                                  // 要改变的属性
                              }];
②如何使用UIView block关键帧动画?

我们只需要在UIView block关键帧动画的animationsblock里直接增加关键帧就可以了,再在增加关键帧方法的animationsblock里把可动画属性改变为目标值就可以了。

(3)UIView block过渡动画
①什么是UIView block过渡动画?

前面我们学习了UIView block基础动画和UIView block关键帧动画,但我们知道它俩其实都是UIView block属性动画,即只能用来对view的可动画属性做动画。那么如果我们现在想要对view的非动画属性改变时(如label的文本,imageView的图片等)做动画,甚至是对view的某些行为(如view的添加和移除,两个view之间切换)做动画,那就只能使用过渡动画了。

同时我们也可以看到,上面UIView block基础动画和UIView block关键帧动画的某些方法里也提供了过渡效果那个配置,也就是说过渡动画也是可以作用于可动画属性的,但是还可以做可动画属性之外的很多效果。

过渡动画的过渡效果可参见UIView block基础动画的过渡效果,是一模一样的。

  • 给单个视图的不可动画属性或视图行为添加过渡动画
[UIView transitionWithView:// 要做动画的视图
                  duration:// 动画时长
                   options:// 过渡动画效果
                animations:^{

                    // 要改变的不可动画属性或图层行为
                } completion:^(BOOL finished) {

                    // 动画完成的回调
                }];
  • 给两个视图切换时添加过渡动画

注意:

  • 这个方法的过渡效果是体现在fromView和toView的父视图上的
  • 这个方法不需要提前把fromView和toView都添在父视图上,只需要先添加fromView就可以了
  • 这个方法在动画过程中,会自动把fromView会从父视图中移除,并把toView添加到父视图上
[UIView transitionFromView:// 旧视图
                    toView:// 新视图
                  duration:// 动画时长
                   options:// 动画过渡效果
                completion:^(BOOL finished) {

                    // 动画完成时的回调
                }];
②如何使用UIView block过渡动画?

我们只需要根据场景是改变单个视图的不可动画属性或视图行为要添加过渡动画还是给两个视图切换时添加过渡动画选择相应的方法就可以了。

三、UIView的block动画应用举例

1、UIView block基础动画
  • 让一条弹幕从右往左飘过去
    (清单1.1)
//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (strong, nonatomic) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.label = [[UILabel alloc] init];
    self.label.backgroundColor = [UIColor magentaColor];
    self.label.frame = CGRectMake(kScreenWidth, 100, kScreenWidth, 30);
    self.label.text = @"嘿Siri,你在哪儿?";
    [self.view addSubview:self.label];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [UIView animateWithDuration:5 animations:^{

        self.label.transform = CGAffineTransformMakeTranslation(-kScreenWidth, 0);
    }];
}


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

@end
  • 漂完之后,我们改变下弹幕内容
    (清单1.2)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [UIView animateWithDuration:5 animations:^{

        self.label.transform = CGAffineTransformMakeTranslation(-kScreenWidth, 0);
    } completion:^(BOOL finished) {

        self.label.text = @"你在哪儿,我就在哪儿!";
    }];
}
  • 我们可以让弹幕匀速地飘过,而不是默认的easyInEasyOut
    (清单1.3)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [UIView animateWithDuration:3 delay:0 options:(UIViewAnimationOptionCurveLinear) animations:^{

        self.label.transform = CGAffineTransformMakeTranslation(-kScreenWidth, 0);
    } completion:^(BOOL finished) {

        self.label.text = @"你在哪儿,我就在哪儿!";
    }];
}
  • 让弹幕弹一弹
    (清单1.4)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [UIView animateWithDuration:3 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:5 options:(UIViewAnimationOptionCurveLinear) animations:^{

        self.label.transform = CGAffineTransformMakeTranslation(-kScreenWidth, 0);
    } completion:^(BOOL finished) {

        self.label.text = @"你在哪儿,我就在哪儿!";
    }];
}

图片 4

1.gif

2、UIView block关键帧动画

类似FaceBook登录界面,登录失败那种输入框抖动的效果。要是使用基础动画的话,可能就得平移一次,再开一个基础动画再平移一次,得开好几个基础动画,关键帧动画的话就开一个动画就可以了,添关键帧就行了。

(清单1.5)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (strong, nonatomic) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.label = [[UILabel alloc] init];
    self.label.backgroundColor = [UIColor cyanColor];
    self.label.frame = CGRectMake(0, 100, kScreenWidth, 30);
    self.label.text = @"请登录";
    [self.view addSubview:self.label];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    self.label.text = @"登录失败";

    [UIView animateKeyframesWithDuration:0.5 delay:0 options:(UIViewKeyframeAnimationOptionCalculationModePaced) animations:^{

        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1/4.0 animations:^{

            self.label.transform = CGAffineTransformMakeTranslation(10, 0);
        }];
        [UIView addKeyframeWithRelativeStartTime:1/4.0 relativeDuration:1/4.0 animations:^{

            self.label.transform = CGAffineTransformMakeTranslation(-10, 0);
        }];
        [UIView addKeyframeWithRelativeStartTime:2/4.0 relativeDuration:1/4.0 animations:^{

            self.label.transform = CGAffineTransformMakeTranslation(10, 0);
        }];
        [UIView addKeyframeWithRelativeStartTime:3/4.0 relativeDuration:1/4.0 animations:^{

            self.label.transform = CGAffineTransformMakeTranslation(0, 0);
        }];
    } completion:^(BOOL finished) {

        NSLog(@"动画结束了");
    }];
}


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

@end

图片 5

1.gif

3、UIView block过渡动画
(1)给单个视图的不可动画属性或视图行为添加过渡动画
  • 切换imageView的图片和label的文本

(清单1.6)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (strong, nonatomic) UIImageView *imageView;
@property (strong, nonatomic) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.imageView = [[UIImageView alloc] init];
    self.imageView.frame = CGRectMake(0, 64, kScreenWidth, kScreenWidth);
    self.imageView.image = [UIImage imageNamed:@"0.jpg"];
    [self.view addSubview:self.imageView];

    self.label = [[UILabel alloc] init];
    self.label.frame = CGRectMake(0, kScreenWidth   100, kScreenWidth, 30);
    self.label.text = @"奥黛丽赫本";
    self.label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.label];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSInteger num = arc4random()%7;

    // 改变imageView的图片,淡入淡出效果
    [UIView transitionWithView:self.imageView duration:3 options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveLinear) animations:^{

        self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg", num]];
    } completion:nil];

    // 改变label的文本,二维翻转效果
    [UIView transitionWithView:self.label duration:3 options:(UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionCurveLinear) animations:^{

        switch (num) {
            case 0:
                self.label.text = @"奥黛丽·赫本";
                break;
            case 1:
                self.label.text = @"苏菲·玛索";
                break;
            case 2:
                self.label.text = @"泰勒·斯威夫特";
                break;
            case 3:
                self.label.text = @"安妮·海瑟薇";
                break;
            case 4:
                self.label.text = @"娜塔丽·波特曼";
                break;
            case 5:
                self.label.text = @"凯拉·奈特利";
                break;
            case 6:
                self.label.text = @"杰西卡·阿尔芭";
                break;
        }
    } completion:nil];
}


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

@end

图片 6

1.gif

  • 淡入淡出的效果添加view
    (清单1.7)
//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (strong, nonatomic) UIImageView *imageView;
@property (strong, nonatomic) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.imageView = [[UIImageView alloc] init];
    self.imageView.frame = CGRectMake(0, 64, kScreenWidth, kScreenWidth);
    self.imageView.image = [UIImage imageNamed:@"0.jpg"];

    self.label = [[UILabel alloc] init];
    self.label.frame = CGRectMake(0, kScreenWidth   100, kScreenWidth, 30);
    self.label.text = @"奥黛丽赫本";
    self.label.textAlignment = NSTextAlignmentCenter;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [UIView transitionWithView:self.view duration:3 options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveLinear) animations:^{

        [self.view addSubview:self.imageView];
        [self.view addSubview:self.label];
    } completion:nil];
}


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

@end

图片 7

1.gif

(2)给两个视图切换时添加过渡动画
  • 例如切换登录和注册视图(当然这个也可以UIViewController的方法来替换,有同样的效果)

图片 8

1.gif

本文由奥门新萄京8522发布于动漫动画,转载请注明出处:庆父不死,Android补间动画

关键词: