Android笔记系列--动画

篇幅比较长,耐心点看,总结了Android中有关动画的细节,包括一些使用的小例子。
源码地址:
https://github.com/StarsAaron/AnimationTestDemo/tree/master

动画

1. View Animation 视图动画

1.1 Frame Animation 帧动画

使用方法:
使用时需要在res下的drawable文件夹中放入需要动画显示的图片,同时在该文件夹中新建一个xml文件。

anim_list.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >
<item android:drawable="@drawable/frame1"
        android:duration="500"/>
<item android:drawable="@drawable/frame2"
        android:duration="500"/>
<item android:drawable="@drawable/frame3"
        android:duration="500"/>
<item android:drawable="@drawable/frame4"
        android:duration="500"/>
<item android:drawable="@drawable/frame5"
        android:duration="500"/>
</animation-list>

给控件设置动画:

image.setBackgroundResource(R.drawable.anim_list);

开启动画:

AnimationDrawable animation_drawable = (AnimationDrawable)image.getBackground();
animation_drawable.start();

停止动画:

animation_drawable.stop();

1.2 Tween Animation 补间动画

知识点:
1) 四种类型动画:alphascaletranslaterotate 的xml文件和代码定义方式。
2) Interpolator 插补器使用
3) set 动画组合

注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式

Android 使用 Animation 代表抽象的动画类,它包括如下几个子类:

  • AlphaAnimation :透明度改变的动画。需指定动画起、止的透明度(0~1)及持续时间。
  • ScaleAnimation :大小缩放的动画。需指定动画起、止的缩放比(X、Y 轴向缩放参数)及持续时间。还应通过 pivotX、pivotY 指定缩放中心的坐标。
  • TranslateAnimation :位移变化的动画。需指定动画起、止的位置(X、Y 坐标)及持续时间。
  • RotateAnimation :旋转动画。需指定动画起、止的旋转角度(X、Y 轴向缩放参数)及持续时间。还应通过 pivotX、pivotY 指定旋转轴心的坐标。

一旦在程序中通过 AnimationUtils 得到代表补间动画的 Animation 之后,即可调用 View 的如下方法开始对该 View 执行动画。

startAnimation(Animation anim);

Animation类是所有动画(scale、alpha、translate、rotate)的基类。

它所具有的标签及对应函数为:

xml属性代码方法描述
android:durationsetDuration(long)动画持续时间,以毫秒为单位
android:fillAftersetFillAfter(boolean)如果设置为true,控件动画结束时,将保持动画最后时的状态
android:fillBeforesetFillBefore(boolean)如果设置为true,控件动画结束时,还原到开始动画前的状态
android:fillEnabledsetFillEnabled(boolean)与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
android:repeatCountsetRepeatCount(int)重复次数
android:repeatModesetRepeatMode(int)重复类型,有reverse和restart两个值,取值为RESTART或 REVERSE,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
android:interpolatorsetInterpolator(Interpolator)设定插值器,其实就是指定的动作效果,比如弹跳效果等
1.2.1 四种变化
1) alpha透明度

xml中定义

alpha标签——调节透明度
1. 自身属性

  • android:fromAlpha 动画开始的透明度,从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明
  • android:toAlpha 动画结束时的透明度,也是从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明

2. 从Animation类继承的属性

注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式

例子:tween_alphaanim.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="3000"
       android:fillBefore="true"
       android:fromAlpha="1.0"
       android:toAlpha="0.1">
</alpha>
    <!-- 透明度控制动画效果 alpha
            浮点型值:
                fromAlpha 属性为动画起始时透明度
                toAlpha   属性为动画结束时透明度
                说明:
                    0.0表示完全透明
                    1.0表示完全不透明
                以上值取0.0-1.0之间的float数据类型的数字

            长整型值:
                duration  属性为动画持续时间
                说明:
                    时间以毫秒为单位
    -->

控件使用动画:

// 透明度
Animation alpaAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_alphaanim);
view.startAnimation(alpaAnimation);

代码中定义AlphaAnimation

对应的构造函数为:

AlphaAnimation(Context context, AttributeSet attrs) 同样,从本地XML加载动画,基本不用
AlphaAnimation(float fromAlpha, float toAlpha)

例子:

// 定义透明度动画
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f, 0.1f);
alphaAnim.setDuration(3000);
alphaAnim.setFillBefore(true);
// 使用动画
view.startAnimation(alphaAnim);
2) scale 缩放

scale标签——调节尺寸

1. 自有属性

  • android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
  • android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
  • android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
  • android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
  • android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
  • android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。

2. 从Animation类继承的属性

Animation类是所有动画(scale、alpha、translate、rotate)的基类,这里以scale标签为例,讲解一下,Animation类所具有的属性及意义。关于Animation类的官方文档位置为:《Animation》

  • android:duration 动画持续时间,以毫秒为单位
  • android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
  • android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
  • android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
  • android:repeatCount 重复次数
  • android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
  • android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。

xml中定义

scale标签——调节尺寸

1、自有属性

scale标签是缩放动画,可以实现动态调控件尺寸的效果,有下面几个属性:
android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。

2、从Animation类继承的属性

注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式

例子:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="700"
       android:fillBefore="true"
       android:fromXScale="0.0"
       android:fromYScale="0.0"
       android:pivotX="50%"
       android:pivotY="50%"
       android:repeatCount="1"
       android:repeatMode="restart"
       android:toXScale="1.4"
       android:toYScale="1.4"
    />

     <!-- 
    Animation变化坐标点的参照类型
    上面看到,RotateAnimation、ScaleAnimation、TranslateAnimation都存在一对pivotXType,pivotYType参数,
    它们是用来指定点的参照类型,使用int类型以静态常量的形式定义在Animation中,它有如下个值:
    ABSOLUTE:以绝对坐标为参照。
    RELATIVE_TO_PARENT:以父容器为参照。
    RELATIVE_TO_SELF:以当前容器为参照。
      细心的朋友有发现到,在使用XML定义动画资源的时候,没有关于pivotXType、pivotYType两个属性,其实它们结合到了设定点的坐标中中,
    以 pivotXValue、pivotYValue两个属性替代,其中如果需要设定为父容器为参照,需要在属性值后面加"p"即可。 
    -->

    <!-- 尺寸伸缩动画效果 scale
           属性:interpolator 指定一个动画的插入器
            在我试验过程中,使用android.res.anim中的资源时候发现
            有三种动画插入器:
                accelerate_decelerate_interpolator  加速-减速 动画插入器
                accelerate_interpolator           加速-动画插入器
                decelerate_interpolator           减速- 动画插入器
            其他的属于特定的动画效果
          浮点型值:

                fromXScale 属性为动画起始时 X坐标上的伸缩尺寸    
                toXScale   属性为动画结束时 X坐标上的伸缩尺寸     

                fromYScale 属性为动画起始时Y坐标上的伸缩尺寸    
                toYScale   属性为动画结束时Y坐标上的伸缩尺寸    

                说明:
                     以上四种属性值    

                        0.0表示收缩到没有 
                        1.0表示正常无伸缩     
                        值小于1.0表示收缩  
                        值大于1.0表示放大

                pivotX     属性为动画相对于物件的X坐标的开始位置(坐标原点X点坐标)
                pivotY     属性为动画相对于物件的Y坐标的开始位置(坐标原点Y点坐标)

                说明:
                        以上两个属性值 从0%-100%中取值
                        50%为物件的X或Y方向坐标上的中点位置

            长整型值:
                duration  属性为动画持续时间
                说明:   时间以毫秒为单位

            布尔型值:
                fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用
    -->

tween_alphaanim.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="3000"
       android:fillBefore="true"
       android:fromAlpha="1.0"
       android:toAlpha="0.1">
</alpha>
    <!-- 透明度控制动画效果 alpha
            浮点型值:
                fromAlpha 属性为动画起始时透明度
                toAlpha   属性为动画结束时透明度
                说明:
                    0.0表示完全透明
                    1.0表示完全不透明
                以上值取0.0-1.0之间的float数据类型的数字

            长整型值:
                duration  属性为动画持续时间
                说明:
                    时间以毫秒为单位
    -->

控件使用动画:

// 缩放
Animation scaleAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_scaleanim);
view.startAnimation(scaleAnimation);

代码中定义ScaleAnimation

ScaleAnimation有下面几个构造函数:
- ScaleAnimation(Context context, AttributeSet attrs) 从XML文件加载动画,基本用不到
- ScaleAnimation(float fromX, float toX, float fromY, float toY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

第一个构造函数是从本地XML文件加载动画,基本用不到的,我们主要看下面三个构造函数。

在标签属性android:pivotX中有三种取值,数,百分数,百分数p;体现在构造函数中,就是最后一个构造函数的pivotXType,它的取值有三个:
- Animation.ABSOLUTE
- Animation.RELATIVE_TO_SELF
- Animation.RELATIVE_TO_PARENT

例子:

// 伸缩动画
Animation scaleAnim = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnim.setDuration(700);
// 使用动画
view.startAnimation(scaleAnim);
3) rotate旋转

rotate标签——旋转

1. 自身属性
- android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p

2. 从Animation类继承的属性
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。

xml中定义

rotate标签——旋转

1. 自身属性

  • android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
  • android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
  • android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
  • android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p

2. 从Animation类继承的属性

注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式

例子:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:fillAfter="true"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="650">
</rotate>

    <!-- rotate 旋转动画效果
           属性:interpolator 指定一个动画的插入器
                 在我试验过程中,使用android.res.anim中的资源时候发现
                 有三种动画插入器:
                    accelerate_decelerate_interpolator     加速-减速 动画插入器
                    accelerate_interpolator                加速-动画插入器
                    decelerate_interpolator                减速- 动画插入器
                 其他的属于特定的动画效果

           浮点数型值:
                fromDegrees 属性为动画起始时物件的角度    
                toDegrees   属性为动画结束时物件旋转的角度 可以大于360度   


                说明:
                         当角度为负数——表示逆时针旋转
                         当角度为正数——表示顺时针旋转              
                         (负数from——to正数:顺时针旋转)   
                         (负数from——to负数:逆时针旋转) 
                         (正数from——to正数:顺时针旋转) 
                         (正数from——to负数:逆时针旋转)       

                pivotX     属性为动画相对于物件的X坐标的开始位置
                pivotY     属性为动画相对于物件的Y坐标的开始位置

                说明:        以上两个属性值 从0%-100%中取值
                             50%为物件的X或Y方向坐标上的中点位置

            长整型值:
                duration  属性为动画持续时间
                说明:       时间以毫秒为单位
    -->

控件使用动画:

// 旋转
Animation rotateAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_rotateanim);
view.startAnimation(rotateAnimation);

代码中定义RotateAnimation

对应的构造函数有:

  • RotateAnimation(Context context, AttributeSet attrs)  从本地XML文档加载动画,同样,基本不用
    RotateAnimation(float fromDegrees, float toDegrees)
  • RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
  • RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

RotateAnimation跟ScaleAnimation差不多,关键问题同样是pivotXType和pivotYType的选择,同样有三个取值:Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT;

例子:

// 旋转动画
Animation rotateAnim = new RotateAnimation(0, -650, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnim.setDuration(3000);
rotateAnim.setFillAfter(true);
// 使用动画
view.startAnimation(rotateAnim);
4) translate平移

translate标签 —— 平移

1. 自身属性

  • android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
  • android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
  • android:toXDelta 结束点X轴坐标
  • android:toYDelta 结束点Y轴坐标

2. 从Animation类继承的属性

  • android:duration 动画持续时间,以毫秒为单位
  • android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
  • android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
  • android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
  • android:repeatCount 重复次数
  • android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
  • android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。

xml中定义

translate标签 —— 平移

1. 自身属性

  • android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
  • android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
  • android:toXDelta 结束点X轴坐标
  • android:toYDelta 结束点Y轴坐标

2. 从Animation类继承的属性

  • android:duration 动画持续时间,以毫秒为单位
  • android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
  • android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
  • android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
  • android:repeatCount 重复次数
  • android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
  • android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。

例子:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="2000"
           android:fillBefore="true"
           android:fromXDelta="0"
           android:fromYDelta="0"
           android:toXDelta="-80"
           android:toYDelta="-80">
</translate>
    <!-- translate 位置转移动画效果
            整型值:
                fromXDelta 属性为动画起始时 X坐标上的位置
                toXDelta   属性为动画结束时 X坐标上的位置
                fromYDelta 属性为动画起始时 Y坐标上的位置
                toYDelta   属性为动画结束时 Y坐标上的位置
                注意:
                         没有指定fromXType toXType fromYType toYType 时候,
                         默认是以自己为相对参照物
            长整型值:
                duration  属性为动画持续时间
                说明:   时间以毫秒为单位
    -->
    <!-- AnimationSet: http://developer.android.com/reference/android/view/animation/AnimationSet.html-->

控件使用动画:

// 平移
Animation translateAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_translateanim);
view.startAnimation(translateAnimation);

代码中定义TranslateAnimation

对应的构造函数为:

  • TranslateAnimation(Context context, AttributeSet attrs) 同样,基本不用
  • TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
  • TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)

由于fromXDelta、fromYDelta、toXDelta、toYDelta这三个属性都具有三种状态,所以在构造函数中,最理想的状态就是第三个构造函数,能够指定每个值的类型,第二个构造函数:TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)使用是绝对数值。只有最后一个构造函数可以指定百分数和相对父控件的百分数。

例子:

// 平移动画
Animation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80);
translateAnim.setDuration(2000);
translateAnim.setFillBefore(true);
// 使用动画
view.startAnimation(translateAnim);

AnimatiorSet组合

xml中定义

set标签——定义动作合集
Set标签就可以将几个不同的动作定义成一个组;set标签自已是没有属性的,他的属性都是从Animation继承而来,但当它们用于Set标签时,就会对Set标签下的所有子控件都产生作用。

属性有:(从Animation类继承的属性)

例子:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="3000"
     android:fillAfter="true">
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>
    <scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.4"
        android:toYScale="1.4"/>
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="720"/>
</set>

    <!-- 透明度控制动画效果 alpha
            浮点型值:
                fromAlpha 属性为动画起始时透明度
                toAlpha   属性为动画结束时透明度
                说明:
                    0.0表示完全透明
                    1.0表示完全不透明
                以上值取0.0-1.0之间的float数据类型的数字

            长整型值:
                duration  属性为动画持续时间
                说明:
                    时间以毫秒为单位
    -->

控件使用动画:

// 动画集
Animation setAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_setanim);
view.startAnimation(setAnimation); 

代码中定义

  • AnimationSet(Context context, AttributeSet attrs) 同样,基本不用
  • AnimationSet(boolean shareInterpolator) shareInterpolator取值true或false,取true时,指在AnimationSet中定义一个插值器(interpolater),它下面的所有动画共同。如果设为false,则表示它下面的动画自己定义各自的插值器。

例子:

// 组合动画
AnimationSet setAnim = new AnimationSet(true);
setAnim.addAnimation(alphaAnim);
setAnim.addAnimation(scaleAnim);
setAnim.addAnimation(rotateAnim);
setAnim.setFillAfter(true);
// 使用动画
view.startAnimation(setAnim);

Interpolator插值器

Interpolator属性是Animation类的一个XML属性,所以alpha、scale、rotate、translate、set都会继承得到这个属性。

InterPolator 根据特定算法计算出整个动画所需动态插入帧的密度和位置。
它是一个接口,定义了所有 Interpolator 都需要实现的方法:
float getInterpolation(float input)
开发者可通过实现 Interpolator 来控制动画的变化速度。

插值器类:

类名描述
AccelerateDecelerateInterpolator在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator开始的时候向后然后向前甩
AnticipateOvershootInterpolator开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator动画结束的时候弹起
CycleInterpolator动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator在动画开始的地方快然后慢
LinearInterpolator以常量速率改变
OvershootInterpolator向前甩一定值后再回到原来位置
xml中定义

为了在动画资源文件中指定补间动画所使用的 Interpolator,定义动画的元素 <set.../><alpha.../><scale.../><translate.../><rotate.../> 都可指定一个 android:interpolator 属性以指定动画的变化速度。Android 系统的 R.anim 类中包含了大致常量,它们定义了不同的动画速度。如:

  • @android:linear_interpolator :匀速变换
  • @android:accelerate_interpolator :加速变换
  • @android:decelerate_interpolator :减速变换

    注:上述常量的写法规律,其实是把系统提供的 Interpolator 实现类的类名的驼峰写法改为下划线写法即可。

例子:

scale标签

先看下XML代码:(从控件中心点,从0放大到1.4倍,保持结束时的状态)

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:fromXScale="0.0"
    android:toXScale="1.4"
    android:fromYScale="0.0"
    android:toYScale="1.4"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="700"
    android:fillAfter="true"
/>

rotate标签
先看下XML代码:(从控件中心点,从0放大到1.4倍,保持结束时的状态)

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%
    android:duration="700"
    android:fillAfter="true"
/>

alpha标签
将透明度从0变成1.0,使用不同的插值器看看有什么不同(因为只是透明度的变化,所以基本看不出来有什么不同)

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:duration="3000"
    android:fillAfter="true"
/>

translate标签

把控件从(0,0)平移到(-200,-200)的位置,保持结束时状态不变,使用不同插值器。

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:fromXDelta="0"
    android:toXDelta="-200"
    android:fromYDelta="0"
    android:toYDelta="-200"
    android:duration="2000"
    android:fillAfter="true"
/>
代码中定义

Android 为 Interpolator 提供了如下几个实现类:

  • LinearInterpolator :动画以匀速改变。
  • AccelerateInterpolator :动画以匀加速改变。
  • AccelerateDecelerateInterpolator :动画的改变以匀加速开始,以匀减速结束,中间改变最快。
  • CycleInterpolator :动画循环播放特定的次数,变化速度按正统曲线改变。
  • DecelerateInterpolator :动画以匀减速改变。

例子:

// 插播器动画
Animation interpolateScaleAnim = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
interpolateScaleAnim.setInterpolator(new BounceInterpolator());
interpolateScaleAnim.setDuration(3000);

// 使用动画
view.startAnimation(interpolateScaleAnim ); 

动画监听

AnimationSet as=new AnimationSet(true);
RotateAnimation al=new RotateAnimation(0,-720,Animation.RELATIVE_TO_PARENT
,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
al.setDuration(3000);
al.setAnimationListener(new AnimationListener() {
    public void onAnimationStart(Animation animation) {
    }
    public void onAnimationEnd(Animation animation) {
    }
    public void onAnimationRepeat(Animation animation) {
    }
});
as.addAnimation(al);
iv.startAnimation(as);

2. Property Animation属性动画

从某种角度看,属性动画是增强版的补间动画,其强大体现在两方面:

  • 补间动画只能定义两个关键帧在透明度、旋转、倾斜、位移这4个方面的变化,而属性动画可以定义任何属性的变化。
  • 补间动画只能对 UI 组件执行动画,而属性动画几乎可以对任何对象执行动画。

属性动画也需要定义如下几方面属性:

  • android:duration :动画持续时间。默认值 300 毫秒。
  • android:interpolator :动画插值方式。与补间动画中插值属性作用类似。
  • android:repeatCount :动画重复次数。
  • android:repeatMode :重复方式。指定动画结束后,从头重播还是反向播放。

2.1 两种属性动画

1) ValueAnimator

可按如下4个步骤:

  • 调用 ValueAnimator 的 ofInt()、ofFloat() 或 ofObject() 静态方法创建 ValueAnimator 实例。
  • 调用 ValueAnimator 的 setXxx() 设置动画持续时间、插值方式、重复次数等。
  • 调用 ValueAnimator 的 start() 方法启动动画。

为 ValueAnimator 注册 AnimatorUpdateListener 监听器,用以监听 ValueAnimator 计算出来的值的改变(可通过 getAnimatedValue() 方法获取当前帧的值),并将这些值应用到指定对象。

例子:

ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight());
animator.setTarget(mBlueBall);
animator.setDuration(1000).start();
// animator.setInterpolator(value)
animator.addUpdateListener(new AnimatorUpdateListener() {
       @Override
       public void onAnimationUpdate(ValueAnimator animation) {
             view.setTranslationY((Float) animation.getAnimatedValue());
       }
});
2) ObjectAnimator

ObjectAnimator 可直接将 ValueAnimator 在动画过程中计算出来的值应用到指定对象的指定属性上,不需要注册监听器。
使用 ObjectAnimator 的 ofInt()、ofFloat() 或 ofObject() 静态方法创建 ValueAnimator 实例时需要指定具体的对象及其属性名。

使用 ObjectAnimator 需注意:

  • 须为该对象对应的属性提供 setter 方法,例如 setAlpha(float value) 方法。
  • 调用 ObjectAnimator 的 ofInt()、ofFloat() 或 ofObject() 工厂方法时 values… 参数只提供了一个结束值。因而该对象应为该属性提供一个 getter 方法以返回一个开始值。

如果动画的对象是 View,为了能显示动画效果,可能还需在 onAnimationUpdate() 事件监听方法中调用 View.invalidate() 方法来刷新屏幕的显示。(比如对 Drawable 对象的 color 属性执行动画)。
不过 View 定义的 setter 方法(如 setAlpha()、setTranslationX() )都会自动调用 invalidate() 方法了。

代码定义例子:

ObjectAnimator anim = ObjectAnimator
.ofFloat(view, "zhy", 1.0F, 0.2F)
.setDuration(500);
anim.start();

anim.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
            float cVal = (Float) animation.getAnimatedValue();
            view.setAlpha(cVal);
            view.setScaleX(cVal);
            view.setScaleY(cVal);
    }
});

XML定义例子:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType" >
</objectAnimator>

调用:

// 加载动画
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);
anim.setTarget(view);
anim.start();

2.2 AnimatorSet组合动画

使用set标签,有一个orderring属性

值:

  • together 同时播放
  • sequentially 表示一个接一个执行

Xml例子:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together" >
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleX"
        android:valueFrom="1"
        android:valueTo="0.5" >
    </objectAnimator>
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="0.5" >
    </objectAnimator>
</set>

// 加载动画
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);
mMv.setPivotX(0);
mMv.setPivotY(0);
//显式的调用invalidate
mMv.invalidate();
anim.setTarget(mMv);
anim.start();

代码例子:

public void togetherRun(View view) {
    ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",1.0f, 2f);
    ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",1.0f, 2f);
      AnimatorSet animSet = new AnimatorSet();
      animSet.setDuration(2000);
    animSet.setInterpolator(new LinearInterpolator());
    //两个动画同时执行
    animSet.playTogether(anim1, anim2);
//animSet.playSequentially(items)
    animSet.start();
}

public void playWithAfter(View view) {
    float cx = mBlueBall.getX();
    ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",1.0f, 2f);
    ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",1.0f, 2f);
    ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,"x", cx, 0f);
    ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,"x", cx);

    /**
     * anim1,anim2,anim3同时执行
     * anim4接着执行
     */
     AnimatorSet animSet = new AnimatorSet();
     animSet.play(anim1).with(anim2);
     animSet.play(anim2).with(anim3);
     animSet.play(anim4).after(anim3);
     animSet.setDuration(1000);
     animSet.start();
}

2.3 使用PropertyValuesHolder 创建实例

ValueAnimator和ObjectAnimator除了通过ofInt(),ofFloat(),ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例。

PropertyValuesHolder中有很多函数,有些函数的api等级是11,有些函数的api等级是14和21;

PropertyValuesHolder这个类可以先将动画属性和值暂时的存储起来,后一起执行,在有些时候可以使用替换掉AnimatorSet,减少代码量。

四个构造方法:

  • public static PropertyValuesHolder ofFloat(String propertyName, float… values)
  • public static PropertyValuesHolder ofInt(String propertyName, int… values)
  • public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object… values)
  • public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe… values)

KeyFrame关键帧 ,一个关键帧必须包含两个原素,第一时间点,第二位置。

构造方法:

/**
 * ofFloat
 */
public static Keyframe ofFloat(float fraction) 
public static Keyframe ofFloat(float fraction, float value)
/**
 * ofInt
 */
public static Keyframe ofInt(float fraction)
public static Keyframe ofInt(float fraction, int value)

例子:

//keyframe
Keyframe keyframe1 = Keyframe.ofFloat(0.0f,0);
Keyframe keyframe2 = Keyframe.ofFloat(0.25f,-30);
Keyframe keyframe3 = Keyframe.ofFloat(0.5f,0);
Keyframe keyframe4 = Keyframe.ofFloat(0.75f, 30);
Keyframe keyframe5 = Keyframe.ofFloat(1.0f,0);
PropertyValuesHolder rotation = PropertyValuesHolder.ofKeyframe("rotation", keyframe1, keyframe2, keyframe3, keyframe4,keyframe5);

PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",1.0f,0.2f,1.0f);
PropertyValuesHolder color = PropertyValuesHolder.ofInt("BackgroundColor", 0XFFFFFF00, 0XFF0000FF);

ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mButton, alpha, scaleX, scaleY,color,rotation);
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(5000).start();

2.4 3.0后View的自带的动画方法

在SDK11的时候,给View添加了animate方法,更加方便的实现动画效果。
在SDK12,SDK16又分别添加了withStartAction和withEndAction用于在动画前,和动画后执行一些操作。当然也可以.setListener(listener)等操作。

// need API 12
mBlueBall.animate()
            .alpha(0)
            .y(mScreenHeight / 2)
            .setDuration(1000)
            // need API 12
            .withStartAction(new Runnable() {
                    @Override
                    public void run() {
                        Log.e(TAG, "START");
                    }
             })
             // need API 16
            .withEndAction(new Runnable() {
                   @Override
                   public void run() {
                       Log.e(TAG, "END");
                       runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mBlueBall.setY(0);
                                mBlueBall.setAlpha(1.0f);
                       }
                   })
            // 等同上面使用的withEndAction和withStartAction
            .setListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) { }

                    @Override
                    public void onAnimationEnd(Animator animation) { }

                    @Override
                    public void onAnimationCancel(Animator animation) { }

                    @Override
                    public void onAnimationRepeat(Animator animation) { }
}).start();

2.5 LayoutAnimator布局动画

布局动画:接下来看看布局动画,主要是针对viewGroup显示子view比如添加删除或显示子view时以什么动画过渡平滑的显示

主要用到两个类,LayoutAnimatorLayoutTransition

(1)LayoutAnimator设置可控制viewGroup显示子view时以什么样的动画显示平滑出来,但无法控制添加删除子view时仅仅这个子view的动画,这时就要用到(2)

(2)LayoutTransition:可控制子view添加删除时 这个子view平滑过渡的显示

LayoutAnimator

所谓的布局动画是指作用的ViewGroup上,给ViewGroup增加子View时添加一个动画过度效果。
在ViewGroup的xml中添加和这个属性:
android:animateLayoutChanges=”true”

这个效果是android默认的显示的过度效果,我们无法自定义,需要自在定义的过度效果则需要使用LayoutAnimationController类来自定义一个。

代码写法:

/**
     * 设置viewGroup加载子view控件显示时的过载动画,就是以什么方式显示比如旋转、平移、淡化等等
     * 但是动态添加删除一个view这个不生效,这时就用到LayoutTranstion了
     * 第一个参数:需要作用的时间
     * 第二个参数:每个子view显示的delay时间
     * setOrder:有三个取值
     * LayoutAnimationController.ORDER_NORMAL; //顺序显示
     * LayoutAnimationController.ORDER_REVERSE;//反显示
     * LayoutAnimationController.ORDER_RANDOM//随机显示
     */
    private void initLayoutAnim() {
        //设置过渡动画
        ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
        //根据具体需求具体定义,也支持集合动画
//        AlphaAnimation
//        RotateAnimation
//        ScaleAnimation
//        AnimationSet
        sa.setDuration(800);//动画执行时长
        //设置动画显示的属性,0.5f是子view间隔显示时的一个延时偏移量单位是s,默认也是0.5f
        //即控件动画执行起始的时间间隔了0.5s
        LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5f);
        //按顺序显示,其它两种可查看注释
        lac.setOrder(LayoutAnimationController.ORDER_RANDOM);//随机
        llAddViewContainer.setLayoutAnimation(lac);
    }

xml 写法:

<layoutAnimation
    xmlns:android="xxx"
    android:delay="0.5"
    android:animationOrder="normal"
    android:animation="anim/anim_item">
LayoutTransition

过渡的类型一共有四种:

  • LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
  • LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
  • LayoutTransition.DISAPPEARING 当一个View在ViewGroup中消失时,对此View设置的动画
  • LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
  • LayoutTransition.CHANGE 不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画。

注意:动画到底设置在谁身上,此View还是其他View。

LayoutTransition mTransition = new LayoutTransition();
transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
transition.setAnimator(LayoutTransition.CHANGE_APPEARING));
transition.setAnimator(LayoutTransition.APPEARING,null);
transition.setAnimator(LayoutTransition.DISAPPEARING,null);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,null);

使用布局动画:
// 创建一个GridLayout
mGridLayout = new GridLayout(this);
// 设置每列5个按钮
mGridLayout.setColumnCount(5);
// 添加到布局中
viewGroup.addView(mGridLayout);
//设置动画
mGridLayout.setLayoutTransition(mTransition);

复杂例子:

    /**
     * 动态添加删除一个view时,view显示的过渡动画效果
     * ViewGroup中Layout的动画实现
     * 调用 LayoutTransition 对象的 setAnimator() 方法来定义下列动画方式,调用参数是 Animator
     * 对象和以下 LayoutTransition 常量:
     * (1)APPEARING —— 元素在容器中显现时需要动画显示。
     * (2)CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。
     * (3)DISAPPEARING —— 元素在容器中消失时需要动画显示。
     * (4)CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。
     */
    private void initLayoutTransition() {  
        mTransitioner = new LayoutTransition();  
        llAddViewContainer.setLayoutTransition(mTransitioner);

        //view出现时 view自身的动画效果
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 90F, 0F).
                setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
        mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);

        //view 消失时,view自身的动画效果
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "rotationX", 0F, 90F, 0F).
                setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
        mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animator2);

        //view 动画改变时,布局中的每个子view动画的时间间隔
        mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
        mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);

        //为什么这里要这么写?具体我也不清楚,ViewGroup源码里面是这么写的,我只是模仿而已 不这么写貌似就没有动画效果了,所以你懂的!
        //view出现时,导致整个布局改变的动画
        PropertyValuesHolder pvhLeft =
                PropertyValuesHolder.ofInt("left", 0, 1);
        PropertyValuesHolder pvhTop =
                PropertyValuesHolder.ofInt("top", 0, 1);
        PropertyValuesHolder pvhRight =
                PropertyValuesHolder.ofInt("right", 0, 1);
        PropertyValuesHolder pvhBottom =
                PropertyValuesHolder.ofInt("bottom", 0, 1);
        PropertyValuesHolder animator3 = PropertyValuesHolder.ofFloat("scaleX", 1F, 2F, 1F);
        final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
                this, pvhLeft, pvhTop, pvhRight, pvhBottom, animator3).
                setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
        changeIn.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                View view = (View) ((ObjectAnimator) animation).getTarget();
                view.setScaleX(1.0f);
            }
        });
        mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);

        // view消失,导致整个布局改变时的动画  
        //Keyframe 对象中包含了一个时间/属性值的键值对,用于定义某个时刻的动画状态。
        Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
        Keyframe kf1 = Keyframe.ofFloat(0.5f, 2f);
        Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
        PropertyValuesHolder pvhRotation =
                PropertyValuesHolder.ofKeyframe("scaleX", kf0, kf1, kf2);
        final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
                this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation).
                setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
        changeOut.addListener(new AnimatorListenerAdapter() {
            @Overrid
            public void onAnimationEnd(Animator animation) {
                View view = (View) ((ObjectAnimator) animation).getTarget();
                view.setScaleX(1.0f);
            }
        });
        mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
    }

2.6 动画监听

ObjectAnimator changeIn;
changeIn.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        View view = (View) ((ObjectAnimator) animation).getTarget();
        view.setScaleX(1.0f);
    }
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星点点-

请我喝杯咖啡呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值