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的介绍就到这里了,每次总结希望可以给自己更深的印象,也能帮助读者。

最后,源码  —> 点我点我 
  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值