Android的动画可以分为三种:View动画、帧动画和属性动画。View动画通过对场景里的对象不断做图像变换(平移、缩放、旋转、透明度)从而产生动画效果,View动画支持自定义。帧动画通过顺序播放一系列图像从而产生动画效果。属性动画通过动态改变对象的属性从而达到动画效果。关于Android动画的大部分知识点,我用下面这张图来概述。

Android wms 动画 android的动画_xml

一、View动画

View动画支持4中动画效果,分别是平移动画、缩放动画、旋转动画和透明度动画。四种变换效果对应着Animation的四个子类,分别是TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。这四种动画既可以通过XML文件定义,也可以通过代码动态创建。对于View动画,建议采用XML文件定义。创建View动画的XML文件位置路径:res/anim/filename.xml。View动画的描述文件固定语法如下:

<?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>



Alpha属性详解


android:fromAlpha

 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明)


android:toAlpha

 动画结束的透明度,同上



Rotate属性详解

android:fromDegrees 旋转开始角度,正代表顺时针度数,负代表逆时针度数
android:toDegrees  旋转结束角度,正代表顺时针度数,负代表逆时针度数
android:pivotX   缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY  缩放起点Y坐标,同上规律


Scale属性详解

android:fromXScale 初始X轴缩放比例,1.0表示无变化
android:toXScale 结束X轴缩放比例
android:fromYScale 初始Y轴缩放比例
android:toYScale 结束Y轴缩放比例
android:pivotX  缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY 缩放起点Y轴坐标,同上规律


Transtale属性详解

android:fromXDelta 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:fromYDelta      起始点Y轴从标,同上规律
android:toXDelta 结束点X轴坐标,同上规律
android:toYDelta 结束点Y轴坐标,同上规律


View动画实践

在res/ani/下定义myani.xml文件

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="true">

    <alpha
        android:fromAlpha="1"
        android:toAlpha="0.3">
    </alpha>

    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="400"
        android:toYDelta="400">
    </translate>

    <scale
        android:fromXScale="1"
        android:toXScale="2"
        android:fromYScale="1"
        android:toYScale="2">
    </scale>

    <rotate
        android:fromDegrees="0"
        android:toDegrees="60">
    </rotate>


</set>



上面myani.xml文件定义中,我们让动画透明度从1到0.3逐渐变淡,平移位置在x轴y轴移动400像素,缩放倍数从1到2,旋转60度。

通过以下代码加载myani.xml文件,让图片动起来。

Animation ani = AnimationUtils.loadAnimation(PropertyAnimActivity.this, R.anim.myanim);
                ani.setDuration(3000);
                imageView.startAnimation(ani);

代码中我们让动画时间持续3秒,看看实际运行效果:

Android wms 动画 android的动画_xml_02


View动画之LayoutAnimation

关于View动画,我们还要继续探讨一下LayoutAnimaiton,LayoutAnimation作用于ViewGroup的动画效果,比如Activity、Fragment的出现和消失,ListView Item项的加载动画等等。一起来看看几个实际的例子。

1、ListView Item加载动画

在res/anim/文件下新建一个list_anim.xml文件,指定到item_anim.xml

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="70%"
    android:animationOrder="normal"
    android:animation="@anim/item_anim" />



在res/anim/下新建一个item_anim.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
    <translate android:fromYDelta="100%" android:toXDelta="0" android:duration="300" />
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
</set>



在ListView控件中引用list_anim文件:

<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/list_anim"
        android:id="@+id/listView"
        android:background="#242222">
    </ListView>



这样,通过xml文件就实现了ListView Item加载的动画效果啦。效果图如下:


我们还可以用代码动态设置动画效果:

/** 引入动画xml文件 **/
        Animation ani = AnimationUtils.loadAnimation(WeChatSlideViewActivity.this, R.anim.list_anim);

        /** 获取LayoutAnimationController对象,设置delay延时 **/
        LayoutAnimationController controller = new LayoutAnimationController(ani, 1f);

        /** 设置动画加载顺序 **/
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);

        /** 控件绑定动画 **/
        listView.setLayoutAnimation(controller);

实现的效果和上面一样。


2、Activity切换动画

在res/anim/文件下新建一个push_left_in.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="1500"
        android:fromXDelta="100%p"
        android:toXDelta="0" />

    <alpha
        android:duration="1500"
        android:fromAlpha="0.1"
        android:toAlpha="1.0" />
</set>



在res/anim/文件下新建一个push_right_out.xml文件:


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="1500"
        android:fromXDelta="0"
        android:toXDelta="100%p" />

    <alpha
        android:duration="1500"
        android:fromAlpha="1.0"
        android:toAlpha="0.1" />
</set>



在Intent跳转处,给界面跳转加上动画:

Intent intent2 = new Intent(ListActivity.this,MyTextViewActivity.class);
startActivity(intent2);
overridePendingTransition(R.anim.push_left_in,R.anim.push_right_out);



实际运行效果图如下:

Android wms 动画 android的动画_xml_03

注意:overridePendingTransition方法必须位于startActivity()或finish()方法之后执行,否则动画效果将不会起作用。Fragment动画切换效果是在通过FragmentTransation中的setCustomAnimations()方法来实现,需要View动画。当然,也还有其他方式给Activity和Fragment添加切换动画。


二、属性动画

属性动画可以对任何对象做动画效果。属性动画不再像View动画只支持4种类型变换,属性动画中有ValueAnimator,ObjectAnimator和AnimatorSet等概念,通过这些概念可以实现各种绚丽的动画效果。属性动画的默认duration时间间隔是300毫秒,默认帧率10毫秒每帧。注意,属性动画在API11之后才有。如果为了兼容API11之前的系统,建议使用开源动画库nineoldandriods,这样就可以保证在API11前的系统上使用属性动画了。对于属性动画,建议用Java代码动态实现。

1、ValueAnimator

简单介绍一下ValueAnimator的使用,这里我们演示一个自由落体的动画效果,封装一个自由落体的动画方法,让对象在Y轴上平移一段距离:

/** 自由落体 **/
    private void verticalRun(final View view){
        final ValueAnimator ani = ValueAnimator.ofFloat(0, screenHeight, screenHeight - imageView.getHeight());
        ani.setTarget(view);
        ani.setDuration(1000).start();
        ani.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setTranslationY((Float) ani.getAnimatedValue());
            }
        });
    }



实际运行效果如下:

Android wms 动画 android的动画_xml_04


2、ObjectAnimator

ObjectAnimator内部工作机制是通过寻找特定属性的get和set方法,然后通过方法不断的对值进行改变,从而实现动画效果。这里我们对一个View实现背景颜色渐变:

/** 背景颜色渐变 **/
    private void changeColor(View view){
        ValueAnimator ani = ObjectAnimator.ofInt(view, "backgroundColor", 0xFFFF8080, 0xFF8080FF);
        ani.setDuration(3000);
        ani.setEvaluator(new ArgbEvaluator());
        ani.setRepeatCount(ValueAnimator.INFINITE);
        ani.setRepeatMode(ValueAnimator.REVERSE);
        ani.start();
    }

实际运行效果如下:

Android wms 动画 android的动画_动画_05

注意:ValueAnimator.ofFloat(float.... values),方法里面的参数是动画变换的数值,参数个数至少在2个以上。当然ValueAnimator还有很多方法,比如ofInt(int... values),ofObject(TypeEvaluator evaluator, Object... values)等等,大家可以参考官方文档。使用ofObject()方法可以实现高级动画效果,因为可以自己定义估值器传入参数。ObjectAnimator.ofInt(T target, String propertyName, int... values)方法中的参数,target即动画对象,propertyName即动画作用对象的哪个属性,values即动画值得范围。当然ObjectAnimator也还有很多方法,ofFloat(),ofObject()等等,同样可以实现各种高级动画效果。

3、AnimatorSet

AnimatorSet是动画集合,即把两个或多个动画效果集合在一起,在一个View对象实现一系列动画效果。这里我们整合以上两种动画效果,让View对象既做自由落体,又实现背景色渐变:

/** 自由落体+背景色渐变 **/
    private void verticalRunAndChangeColor(final View view){
        final ValueAnimator ani1 = ValueAnimator.ofFloat(0, screenHeight, screenHeight - imageView.getHeight());
        ani1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setTranslationY((Float) ani1.getAnimatedValue());
            }
        });

        ValueAnimator ani2 = ObjectAnimator.ofInt(view, "backgroundColor", 0xFFFF8080, 0xFF8080FF);
        ani2.setEvaluator(new ArgbEvaluator());
        ani2.setRepeatCount(ValueAnimator.INFINITE);
        ani2.setRepeatMode(ValueAnimator.REVERSE);

        AnimatorSet set  = new AnimatorSet();
        set.setDuration(3000);
        set.playTogether(ani1, ani2);
        set.start();
    }



实际运行效果如下:

Android wms 动画 android的动画_android_06


上面动画效果可以看出两个动画效果是同时显示的,因为set.playTogether()方法。我们还可对一系列动画进行串联,让动画效果依次执行,下面的方法展示了先对View对象实现X轴方向的放大,然后实现Y轴方向的放大,之后从当前位置移动到X轴原点位置,然后移动到初始位置:

private void playWithAfter(View view){
        float cx = view.getX();
        ObjectAnimator ani1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 2.0f);
        ObjectAnimator ani2 = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 2.0f);
        ObjectAnimator ani3 = ObjectAnimator.ofFloat(view, "x", cx, 0f);
        ObjectAnimator ani4 = ObjectAnimator.ofFloat(view, "x", cx);

        AnimatorSet set = new AnimatorSet();
        set.play(ani2).after(ani1);
        set.play(ani3).after(ani2);
        set.play(ani4).after(ani3);
        set.setDuration(3000);
        set.start();
     }



实际运行效果如下:

Android wms 动画 android的动画_动画_07

还可以对其中两个或多个动画效果进行并联,然后进行串联,即可以控制多个动画一起执行,然后在某个动画之后执行,我们对动画1,动画2进行了with连接,即这两个动画可以同时执行:

private void playWithAfter(View view){
        float cx = view.getX();
        ObjectAnimator ani1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 2.0f);
        ObjectAnimator ani2 = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 2.0f);
        ObjectAnimator ani3 = ObjectAnimator.ofFloat(view, "x", cx, 0f);
        ObjectAnimator ani4 = ObjectAnimator.ofFloat(view, "x", cx);

        AnimatorSet set = new AnimatorSet();
        set.play(ani2).with(ani1);
        set.play(ani3).after(ani2);
        set.play(ani4).after(ani3);
        set.setDuration(3000);
        set.start();
     }



实际运行效果如下:

Android wms 动画 android的动画_动画效果_08

4、属性动画XML定义

属性动画XML定义文件位置:res/animator/。属性动画描述文件固定语法如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
    
    <objectAnimator
        android:propertyName="scaleX"
        android:duration="3000"
        android:valueFrom="1"
        android:valueTo="2"
        android:startOffset="1"
        android:repeatCount="2"
        android:repeatMode="restart"
        android:valueType="intType">
        
    </objectAnimator>
    <pre name="code" class="java"><span >	</span><animator
        android:duration="3000"
        android:valueFrom="1"
        android:valueTo="2"
        android:startOffset="1"
        android:repeatCount="2"
        android:repeatMode="restart"
        android:valueType="intType">
        
    <span >	</span></animator>

<set> ... </set> </set>


属性动画中各参数解释:<set>标签对应AnimatoreSet,<animator>标签对应ValueAnimator,<objectAnimator>标签对应ObjectAnimator。<set>标签的ordering属性有两个可选值:“together”和“sequentially”,前者代表所有动画同事播放,后者代表前后按顺序播放。ordering默认值是together。

propertyName    属性动画的作用对象的属性名称

duration    动画的时长

valueFrom    属性的起始值

valueTo    属性的结束值

startOffset    动画的延迟时间,当动画开始后,需要延迟多少毫秒才真正播放此动画

repeatCount     动画的重复次数

repeatMode     动画的重复模式

valueType    属性类型 有intType和floatType两个选项,如果是颜色属性,则不需要指定valueType,系统会自动对颜色属性做处理

其中,repeatCount默认值是0,如果为-1,表示动画无限循环;repeatMode有连个选项restart和reverse,前者表示连续重复,后者表示逆向重复。

我们一起来看一个属性动画XML定义的例子:

在res/animator/下新建一个property_animator.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>

    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="0f">
    </objectAnimator>
    
</set>

Java代码执行动画:

/** 获取属性文件 开始动画 **/
                Animator set = AnimatorInflater.loadAnimator(PropertyAnimActivity.this, R.animator.property_animator);
                set.setTarget(imageView);
                set.start();