Android动画之View animation(视图动画)

动画的种类

Android动画可以分为以下3种:
View Animation
视图动画,通多对整个视图不断做图像的变换(平移、缩放、旋转、透明度)产生的动画效果,是一种渐进式动画。

Drawable Animation
图片动画,其实也是逐帧动画,是通过一个接一个的加载Drawable资源来创建动画,按顺序的播放,像一个胶卷。对于视图动画,他只是单独的图片内容在变换,而不是整个视图。很显然,如果图片过多多大就会导致OOM异常。

Property Animation
属性动画,在Android 3.0的(API级别11)引入的,该属性动画系统可以制作动画的任何对象的属性。但是一般来说,属性动画系统是首选的使用方法,因为它更灵活,并提供更多功能。

对于动画的分类,也有不同的,分为2类:View Animation 和 Property Animation,其中 View Animation又可以分为:补间动画和逐帧动画。其实内容多是以上三种,就不纠结这个了。
接下来,将会介绍这三种动画,并实现demo。这篇的主角是View Animation。

View Animation

视图动画的作用对象只能是View,在同一个图形通过在界面上进行透明度,缩放,旋转,平移的变化。

View动画的分类:

view动画支持4中动画效果,分别是:
  • 透明度动画(AlphaAnimation)
  • 缩放动画(ScaleAnimation)
  • 平移动画(TranslateAnimation)
  • 旋转动画(RotateAnimation)
如图所示,图中几个类多是Animation的子类,在java代码中具体实现也是通过这些子类来实现



这4种动画既能分开独立实现,也可以组合实现复合动画AnimationSet。如果这些动画还是满足不了你,可以自定义动画。不过,后面有了属性动画之后,大部分还是可以满足需求。

view动画的实现可以通过Xml来定义,也可以通过java代码来动态设置。对于view动画,建议使用XML来定义动画,可读性好,而且能过复用。而对于属性动画,则建议是通过代码动态设置,后文会介绍。

对于XML实现,有如下诸多属性,当然也不止这些
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

首先先介绍他们公用的属性,其余在单独实现的实现的实现的再介绍:

XML属 性:android:duration             
关联方法:setDuration(long)           
说明:动画持续时间, 默认值是0 (单位ms)                          

XML属 性:android:fillAfter             
关联方法:setFillAfter(boolean)           
说明:表示动画结束后是否保留动画后的状态,true保留动画后状态,false恢复原来状态,默认值是false                          

XML属 性:android:fillBefore           
关联方法:setFillBefore(boolean)       
说明:表示动画结束后是否保留动画前的状态,true恢复原来状态,false保留动画后状态,默认值是true

XML属 性:android:fillEnabled           
关联方法:setFillEnabled(boolean)       
说明:如果设置为true,将fillBefore设置考虑在内                      

XML属 性:android:interpolator         
关联方法:setInterpolator(Interpolator) 
说明:设置动画的变化速率 即插值器,改变动画变换的速度,默认值是@android:anim/accelerate_decelerate_interpolator,即加速减速插值器,在动画开始和结束的时速度较慢,中间时候加速                      

XML属 性:android:repeatCount       
关联方法:setRepeatCount(int)         
说明:设置动画重复执行的次数  ,默认值是0                          
 
XML属 性:android:repeatMode       
关联方法:setRepeatMode(int)           
说明:设置动画重复的模式,其值可以有,restart( 1 ),表示顺序播放,reverse(2)表示重复的时候逆向播放                         
 
XML属 性:android:startOffset       
关联方法:setStartOffset(long)         
说明:设置开始的延迟的时间(单位ms)  ,默认值是0                 
 
坐标类型:
Animation.ABSOLUTE : 绝对数值(默认以px为单位)
Animation.RELATIVE_TO_SELF : 百分数,如:50% (以当前视图的宽度或高度为基数来计算)   
Animation.RELATIVE_TO_PARENT : 百分数+p,如:50%p (以父视图的宽度或高度为基数来计算)

设置监听:view.setAnimationListener(AnimationListener)
启动动画 : view.startAnimation(animation);
结束动画: view.clearAnimation();
.....

下面将详细对每个动画都通过这个2中方式分别实现,XMl实现可读性好,复用性强;java代码实现灵活、快速,因此这2中方式适用于不同的场景时,多比较常用。

准备工作:
1.使用AndroidStudio(或者其他)新建一个工程项目;
2.在res目录下新建anim资源文件(属性动画是新建animator文件);

AlphaAnimation

透明度动画,改变视图整体透明度,透明度值由1~0,从可见到不可见的变化,它的属性较少,最简单的一个。

在XML实现:
首先,新建一个alpha_demo.xml文件,在anim文件,点击右键,new->Android resource file, 文件名:alpha_demo,根节点:alpha
ok,该动画是通过标签<alpha/>实现的,实现代码如下:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:duration="2000">
</alpha>
它属性含义如下:
android:fromAlpha: 表示透明度的起始值,这里设置为0.0,表示完全透明,取值范围0~1;
android:toAlpha:表示透明度的结束值,这里设置为1.0,表示完全不透明,取值范围0~1;;
android:duration 表示动画持续的时间,这里设置为2000,单位是毫秒;

那现在如何java代码中使用这个xml呢? 使用AnimationUtils类的静态方法loadAnimation()来加载XML文件,得到一个Animation对象,如下:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
mImage.startAnimation(animation);
所有的属性多在xml定义好了,这里直接开始动画即可,就是这么简单。

在java实现:
要实现上面一样的功能,就需要用到Animation的子类AlphaAnimation来实现,代码如下:
        AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
        alphaAnimation.setDuration(3000);
        mImage.startAnimation(alphaAnimation);
构造方法:
1.public AlphaAnimation (Context context, AttributeSet attrs)
context:当前上下文
attrs:xml中读取的属性设置

2.public AlphaAnimation (float fromAlpha, float toAlpha)
fromAlpha:动画开始的透明度
toAlpha:动画结束的透明度
ps:第一个构造函数较少用,一般在自定义动画的时候会用到(下面的动画也是一样);第2个方法很直观,也是最常用的。

ScaleAnimation

缩放动画,需要一个坐标点来,即轴点,实现以不同的轴点的缩放效果不同,因此需要先指定pivotX,pivotY确定轴点坐标。默认情况下,从对象view的左上角开始缩放,注意,不是父控件。

在xml实现:
该动画是通过标签<scale/>实现的,实现代码如下:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="3000"
       android:fromXScale="0.0"
       android:fromYScale="0.0"
       android:pivotX="50%"
       android:pivotY="50%"
       android:toXScale="1.0"
       android:toYScale="1.0">
</scale>
属性含义如下:
android:fromXScale:动画开始时,水平方向缩放系数 float型值
android:fromYScale:动画开始时,垂直方向缩放系数float型值
android:toXScale:动画结束时,水平方向缩放系数float型值
android:toYScale:动画结束时,垂直方向缩放系数float型值
android:pivotX:缩放轴点的X坐标(其值可以为:数值、百分数、百分数p),例如:如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY:缩放轴点的Y坐标,规律同pivotX。

在java中加载并开始该动画:
 	Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
        mImage.startAnimation(animation);

在java中实现:
需要使用Animation的子类ScaleAnimation来实现,代码如下:
        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(3000);
        mImage.startAnimation(scaleAnimation);
构造函数:
1.public ScaleAnimation(Context context, AttributeSet attrs)(同上)

2.public ScaleAnimation(float fromX, float toX, float fromY, float toY)
fromX:动画开始时,水平方向缩放系数float型值
toX:动画开始时,垂直方向缩放系数float型值
fromY:动画结束时,水平方向缩放系数float型值
toY:动画结束时,垂直方向缩放系数float型值

3.public ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
pivotX:表示轴点在x方向坐标值,相对于该对象绝对像素位置,0表示该对象的左边缘坐标
pivotY:表示轴点在y方向坐标值,相对于该对象绝对像素位置,0表示该对象的上边缘坐标
ps:该构造函数 ,坐标类型默认是:Animation.ABSOLUTE ,因此,作用与xml中android:pivotX为数值时 对应

4.public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
pivotXType:X轴坐标的类型(不同类型,计算x轴上的偏移量的方式不同)
pivotXValue:表示轴点在x方向坐标值
pivotYType:Y轴坐标的类型(不同类型,计算y轴上的偏移量的方式不同)
pivotYValue:表示轴点在y方向坐标值

ps:
当pivotXType=Animation.ABSOLUTE时:pivotXValue的值代表绝对像素,与xml中android:pivotX为数值时对应
当pivotXType=Animation.RELATIVE_TO_SELF时:pivotXValue的值代表相对于当前View定位,与xml中android:pivotX为百分数时对应
当pivotXType=Animation.RELATIVE_TO_PARENT:pivotXValue的值代表相对于当前View的父控件定位,与xml中android:pivotX为百分数p时对应

RotateAnimation

旋转动画,与缩放动画较为相似,也需要一个轴点来实现旋转。默认情况下,从对象view的左上角开始旋转,也即是相对于当前view坐标为(0,0)位置。

在xml实现:
该动画是通过标签</rotate>实现的,实现代码如下:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fromDegrees="0"
        android:toDegrees="90">

</rotate>
属性含义:
android:pivotX:旋转轴点的X坐标(其值可以为:数值、百分数、百分数p),例如:如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY:旋转轴点的Y坐标,规律同android:pivotX。
android:fromDegrees:旋转开始的角度,其值可以为正负
android:toDegrees:旋转结束的角度,其值可以为正负
ps:toDegrees -fromDegrees > 0,则顺时针旋转;否则,逆时针旋转。

在java中加载并开始该动画:
	Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.rotate);
        mImage.startAnimation(animation);

在java中实现:
需要使用Animation的子类RotateAnimation 来实现,代码如下:
	RotateAnimation rotateAnimation = new RotateAnimation(0,180);
        rotateAnimation.setDuration(3000);
        mImage.startAnimation(rotateAnimation);
构造函数:
1.public RotateAnimation(Context context, AttributeSet attrs)(同上)

2.public RotateAnimation(float fromDegrees, float toDegrees)
fromDegrees:旋转开始的角度,其值可以为正负
toDegrees:旋转结束的角度,其值可以为正负

3.public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
pivotX:表示轴点在x方向坐标值,相对于该对象绝对像素位置,0表示该对象的左边缘坐标
pivotY:表示轴点在y方向坐标值,相对于该对象绝对像素位置,0表示该对象的上边缘坐标
ps:该构造函数 ,坐标类型默认是:Animation.ABSOLUTE ,因此,作用与xml中android:pivotX为数值时 对应

4.public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType)
pivotXType:X轴坐标的类型(不同类型,计算x轴上的偏移量的方式不同)
pivotXValue:表示轴点在x方向坐标值
pivotYType:Y轴坐标的类型(不同类型,计算y轴上的偏移量的方式不同)
pivotYValue:表示轴点在y方向坐标值

TranslateAnimation

平移动画,实现视图垂直/水平方向位移变化,指定开始的位置,和结束的位置即可。

在xml实现:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:fillAfter="true"
           android:duration="3000"
           android:fromXDelta="50%"
           android:fromYDelta="50%"
           android:toXDelta="50%p"
           android:toYDelta="50%p">
</translate>
属性含义如下:
android:fromXDelta:平移开始X方向坐标(其值可以为:数值、百分数、百分数p,且多可以为正负),其值含义与android:pivotX类似
android:fromYDelta:平移开始Y方向坐标(其值可以为:数值、百分数、百分数p,且多可以为正负),其值含义与android:pivotY类似
android:toXDelta:平移结束X方向坐标(其值可以为:数值、百分数、百分数p,且多可以为正负),其值含义与android:pivotX类似
android:toYDelta:平移结束Y方向坐标(其值可以为:数值、百分数、百分数p,且多可以为正负),其值含义与android:pivotY类似

在java中加载并开始该动画:
	Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
        mImage.startAnimation(animation);

在java中实现:
需要使用Animation的子类TranslateAnimation来实现,代码如下:
	TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_PARENT,0,Animation.RELATIVE_TO_PARENT,0.5f);
        translateAnimation.setDuration(3000);
        translateAnimation.setFillAfter(true);
        mImage.startAnimation(translateAnimation);
构造函数:
1. public TranslateAnimation(Context context, AttributeSet attrs)(同上)

2.public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
fromXDelta:表示在平移开始X方向的绝对像素值
toXDelta:表示在平移开始Y方向的绝对像素值
fromYDelta:表示在平移结束X方向的绝对像素值
toYDelta:表示在平移结束Y方向的绝对像素值
ps:该构造函数 ,坐标类型默认是:Animation.ABSOLUTE ,因此,作用与xml中android:fromXDelta为数值时 对应

3.public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
fromXType:平移开始X轴的坐标类型(不同类型,计算x轴上的偏移量的方式不同)
fromXValue:平移开始X轴的坐标,其值的含义与fromXType的类型有关
toXType:平移结束Y轴的坐标类型(不同类型,计算x轴上的偏移量的方式不同)
toXValue:平移结束X轴的坐标,其值的含义与toXType的类型有关
fromYType:平移开始Y轴的坐标类型(不同类型,计算x轴上的偏移量的方式不同)
fromYValue:平移开始Y轴的坐标,其值的含义与fromYType的类型有关
toYType:平移结束Y轴的坐标类型(不同类型,计算x轴上的偏移量的方式不同)
fromXType:平移结束Y轴的坐标,其值的含义与toYType的类型有关

AnimationSet

集合动画,如果单一的动画太过于单调,那么就可以将这些单一的动画组合成个性酷炫的动画,同时指定播放的顺序,并且集合里面可以再包含集合。但注意的是,在集合设置的属性对该标签下的所有子控件都产生影响。

在xml实现:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">
    <scale
        android:duration="2000"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:interpolator="@android:anim/linear_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0"
        android:toYScale="0"/>

    <set
        android:duration="2000"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:shareInterpolator="true"
        android:startOffset="2000">
        <scale
            android:fromXScale="0"
            android:fromYScale="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toXScale="1"
            android:toYScale="1"/>
        <rotate
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="180"/>
    </set>
</set>
属性含义:
android:shareInterpolator:子元素是否共享插值器,值为true,表示共同使用;值为false,表示不共享
其余属性多和其他类似,这里如果需要设置播放的顺序,则需要设置android:startOffset属性
在java中加载并开始该动画:
	Animation animation = AnimationUtils.loadAnimation(mContext,R.anim.set);
        mImage.startAnimation(animation);

在java中实现:
需要使用Animation的子类AnimationSet 来实现,代码如下:
	AnimationSet animationSet1 = new AnimationSet(false);//一级集合
        ScaleAnimation scaleAnimation1 = new ScaleAnimation(1, 1.4f, 1, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);

        AnimationSet animationSet2 = new AnimationSet(true);//二级集合
        ScaleAnimation scaleAnimation2 = new ScaleAnimation(1.4f, 0, 1.4f, 0, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
        RotateAnimation rotateAnimation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);

        animationSet2.addAnimation(scaleAnimation2);
        animationSet2.addAnimation(rotateAnimation);
        animationSet2.setInterpolator(new DecelerateInterpolator());
        animationSet2.setDuration(2000);
        animationSet2.setStartOffset(2000);

        animationSet1.addAnimation(scaleAnimation1);
        animationSet1.addAnimation(animationSet2);
        animationSet1.setInterpolator(new AccelerateDecelerateInterpolator());
        animationSet1.setDuration(2000);

        mImage.startAnimation(animationSet1);
构造函数:
1.AnimationSet(Context context, AttributeSet attrs)(同上)
2.public AnimationSet(boolean shareInterpolator)
shareInterpolator:是否共享插值器

动画的监听

如果我们在动画变化的过程中,需要添加什么功能,那么就可以设置监听,比如:
 translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
可以监听动画开始、结束、重复三种状态。

注意:无论您的动画如何移动或调整大小,保存动画的视图的边界将不会自动调整以适应。即使如此,动画仍将被绘制超出其视图的边界,不会被剪辑。但是,如果动画超过父视图的边界,则会发生裁剪。

问题:你是否真正的明白 pivotX 的含义?
轴点坐标值pivotX,pivotY,有三种表达方式:在xml文件,其值有3种类型:数值、百分数、百分数p;在java代码中,其值要根据,三种坐标类型(前方有介绍)来确定。
一般,对于表达方式的第一种、第二种,应该是比较常用的,而且也是比较好理解的,也比较直观。那么问题来了:

提出问题:
如果是使用第三种,相对于父控件定位,你是否能够准确找到轴点位置?是否知道其真正的含义?

猜想:
pivotX = 50%,那么轴点就在该控件(没有覆盖整个屏幕)的中间位置;pivotX = 50%p,那么中心点相对于父控件(覆盖了整个屏幕)就是屏幕的中间点。
对于这个想法,我...我...我...刚开始是这样子想的......

实践:
我们用平移动画来实践,保留动画结束的帧,将其参数设置为:
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f, 
		Animation.RELATIVE_TO_PARENT ,0, Animation.RELATIVE_TO_PARENT, 0.5f);
从相当于父控件的(0,0)    移动到     父控件的(50%,50%),但实际效果是这样子的,与猜想不符:
         
                                                                                            

探索并解决问题:
我们可以点进去看TranslateAnimation ,可以发现:
@Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
        mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
        mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
        mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
    }
然后看resolveSize()方法:
protected float resolveSize(int type, float value, int size, int parentSize) {
        switch (type) {
            case ABSOLUTE:
                return value;
            case RELATIVE_TO_SELF:
                return size * value;
            case RELATIVE_TO_PARENT:
                return parentSize * value;
            default:
                return value;
        }
    }
也许,看到这里,反而觉得猜想没有错。。。莫急,其实动画真正的实现是在这里:
@Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float dx = mFromXDelta;
        float dy = mFromYDelta;
        if (mFromXDelta != mToXDelta) {
            dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
        }
        if (mFromYDelta != mToYDelta) {
            dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
        }
        t.getMatrix().setTranslate(dx, dy);
    }
其中,第一个参数interpolatedTime为动画的进度时间值,取值范围为[0.0f,1.0f],第二个参数Transformation记录着动画某一帧中变形的原始数据。该方法在动画的每一帧显示过程中都会被调用。
这里,我们发现,动画需要绘制的轨迹是dx = mToXDelta ,dy = mToYDelta ,这个值是相对于该控件 需要变化的距离,而不是最终的位置,那么最终猜想:
如果该控件刚好位于屏幕的左上角,则mToXValue就是动画结束的位置;
如果该控件不在屏幕的左上角,则最终动画后的坐标需要加上该控件这个坐标;
最后用表达式表示:
toXValue = fromXType + dx;
toYType = fromYValue + dy;

验证:
因为VieAnimation动画,不能改变视图的属性,即使保留结束后的帧,动画结束后获取的坐标还是和动画前一样的。。。
那我们先得到屏幕的大小,通过简单的一些计算,得到动画结束的位置(通过上面的表达式),在这个位置放上一张图片,看是否可以这张图片重合,看图:
                                                                                                       
可以看到,最后的结论是正确的。
那么,现在你是否明白了pivotX的含义?
但是,然并卵,貌似也很少用到相对于父控件这个参数,笑哭!!!所以理解理解就好吧,哈哈哈。。。

其他使用场景

1.应用于ViewGroup的子元素
我们常用的ViewGroup,比如ListView,我们通常看到,ListView的每个子元素出现时多有一个特定的动画,那么是怎么实现的呢?学完上面的,会觉得特别的简单。
它使用的是LayoutAnimation,它也是一个View动画。下面给ListView添加动画,有以下步骤:

a.定义LayoutAnimation的xml文件,menu_setting_title_list.xml,如下:
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="0.2"
    android:animationOrder="normal"
    android:animation="@anim/left_in">
</layoutAnimation>
属性含义:
android:delay:子元素开始动画的延迟时间。比如,在@anim/left_in定义的动画周期为500ms,那么0.2表示每个item元素需要延迟100ms才出场播放,也可以为百分数。
android:animationOrder:表示子元素动画的顺序。有三种顺序:normal(从小到大正常顺序)、reverse(倒序)、random(随机)。
android:animation:子元素具体的入场动画。

b.给子元素定义具体的动画实现,即实现left_in.xml文件,如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromXDelta="-100%"
        android:toXDelta="0" />
</set>
很简单,从左滑到右边,这个效果即从隐藏到出现,时间为500ms。

c.给ListView指定LayoutAnimation属性,实现动画。
在xml指定:
<ListView
            android:id="@+id/listView_setting_title"
            android:layout_width="378dp"
            android:paddingTop="89.2dp"
            android:layout_height="match_parent"
            android:divider="@color/transparent"
            android:dividerHeight="4dp"
            android:layoutAnimation="@anim/menu_setting_title_list"
            android:listSelector="@color/transparent">
 </ListView>

在java代码指定:
//获取Animation对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.menu_installation_list);
		//得到LayoutAnimationController对象
		LayoutAnimationController controller = new LayoutAnimationController(animation);
		//设置动画播放顺序
		controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
		//设置延迟时间
		controller.setDelay(0.2f);
		//listView设置LayoutAnimation,实现动画
		mMenuTitlesList.setLayoutAnimation(controller);
以上三步就实现LayoutAnimation的设置。

2.应用于Activity的切换
Activity切换过程中,系统有默认的动画,但是很普通。如果我们想自己定义,可以使用 overridePendingTransition(int enterAnim, int exitAnim)来指定动画。其中,
enterAnim:Activity被打开时的动画资源id
exitAnim:Activity被关闭时的动画资源id
代码如下:
startActivity(new Intent(this, MainActivity.class));
overridePendingTransition(R.anim.left_in, R.anim.right_out);
finish();
其中,left_in.xml,right_out.xml 就是自定义的动画

注意的是:该方法必须在startActivity()或者在finish()方法之后调到才有效果!!!切记

3.应用于Fragment的切换
Fragmnet同样也可以添加动画切换,这个应该相对比较少用到。它是通过FragmentTransaction的setCustomAnimations(int enter, int exit)方法来指定动画的。
enter:Fragmnet被打开时的动画资源id;
exit:Fragmne被关闭时的动画资源id;
Fragmnet是在api11才引入,这个动画需要view动画,如果导入的Fragment的是v4包,那么只能支持ViewAnimation,如果是android.app下的,那么也支持Property Animation。使用如下:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction .setCustomAnimations(R.animator.cube_left_in, R.animator.cube_right_out); //使用属性动画
transaction.hide(mFrontFragment).add(R.id.fragment_layout, nextFragment, fragmentTag);
transaction.commit();

接下来看一个集合这3中场景的动画:(由于项目管理的东西比较大,这个就不贴代码了)
                                                                                          


好了,对于ViewAnimation的介绍就到这里了,每次总结希望可以给自己更深的印象,也能帮助读者。

最后,源码  —> 点我点我 
For making animations more real, I created another project named Android Easing Functions which is an implementations of easing functions on Android. So, we need to dependent that project. Step 1 Gradle dependencies { compile 'com.nineoldandroids:library:2.4.0' compile 'com.daimajia.easing:library:1.0.1@aar' compile 'com.daimajia.androidanimations:library:1.1.3@aar' } Maven <dependency> <groupId>com.nineoldandroids</groupId> <artifactId>library</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>com.daimajia.androidanimation</groupId> <artifactId>library</artifactId> <version>1.1.3</version> <type>apklib</type> </dependency> <dependency> <groupId>com.daimajia.easing</groupId> <artifactId>library</artifactId> <version>1.0.1</version> <type>apklib</type> </dependency> Eclipse Download the following jars, and copy them into your libs directory. NineOldAndroid-2.4.0 AndroidEasingFunctions-1.0.0 AndroidViewAnimations-1.1.3 Step 2 Just like play Yo-yo. YoYo.with(Techniques.Tada) .duration(700) .playOn(findViewById(R.id.edit_area)); Effects Attension Flash, Pulse, RubberBand, Shake, Swing, Wobble, Bounce, Tada, StandUp, Wave Special Hinge, RollIn, RollOut,Landing,TakingOff,DropOut Bounce BounceIn, BounceInDown, BounceInLeft, BounceInRight, BounceInUp Fade FadeIn, FadeInUp, FadeInDown, FadeInLeft, FadeInRight FadeOut, FadeOutDown, FadeOutLeft, FadeOutRight, FadeOutUp Flip FlipInX, FlipOutX, FlipOutY Rotate RotateIn, RotateInDownLeft, RotateInDownRight, RotateInUpLeft, RotateInUpRight RotateOut, RotateOutDownLeft, RotateOutDownRight, RotateOutUpLeft, RotateOutUpRight Slide SlideInLeft, SlideInRight, SlideInUp, SlideInDown SlideOutLeft, SlideOutRight, SlideOutUp, SlideOutDown Zoom ZoomIn, ZoomInDown, ZoomInLeft, ZoomInRight, ZoomInUp ZoomOut, ZoomOutDown, ZoomOutLeft, ZoomOutRight, ZoomOutUp Welcome contribute your amazing animation effect. :-D
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值