Android补间动画

2019-11-27 09:46栏目:作品评价

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

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; 

版权声明:本文由手机电玩城发布于作品评价,转载请注明出处:Android补间动画