7_Android动画深入分析

来源:互联网 发布:待机长平板 知乎 编辑:程序博客网 时间:2024/06/05 10:03

Android动画深入分析

0、简介

Android的动画分为三类:View动画、帧动画和属性动画。其实帧动画也属于View动画的一种,只不过它和平移、旋转等常见的View动画在表现形式上略有不同而已。View动画通过对场景里的对象不断做图像变换(平移、缩放、旋转、透明度)从而产生动画效果,它是一种渐进式动画,并且View动画支持自定义。帧动画通过顺序播放一系列图像从而产生动画效果,可以简单理解为图片切换动画,如果图片过多过大就会导致OOM。

属性动画通过动态地改变对象的属性从而达到动画效果。属性动画使API 11的新特性。

1、View动画

View动画的作用对象是View,分别是平移动画、缩放动画、旋转动画和透明度动画。

1)、View动画的种类

View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。这四种动画既可以通过XML来定义,也可以通过代码来动态创建,对于View动画来说,建议采用XML来定义动画,因为xml格式的动画可读性更好。

View动画既可以是单个动画,也可以由一系列动画组成。<set>标签表示动画集合,对应AnimationSet类,它可以包含若干个动画,并且它的内部也可以嵌套其他动画集合。它的两个属性的含义为:

android:interpolator:表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。默认:加速减速插值器。

android:shareInterpolator:表示集合中的动画是否和集合共享同一个插值器。如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值。

<translate>标签标示平移动画,对应TranslateAnimation,它可以使一个View在水平和竖直方向完成平移的动画效果,它的一系列属性含义如下:

android:fromXDelta-----表示x的起始值,比如0;

android:toXDelta-----表示x的结束值,比如100;

android:fromYDelta------表示y的起始值;

android:toYDelta-------表示y的结束值。

<set xmlns:android="http://schemas.android.com/apk/res/android">    <translate        android:duration="300"        android:fromXDelta="0.0"        android:interpolator="@android:anim/linear_interpolator"        android:toXDelta="100.0%p" /></set>
<scale>标签表示缩放动画,对应ScaleAnimation,它可以使View具有放大或者缩小的动画效果,它的一系列属性的含义如下:

android:fromXScale----水平方向缩放的起始值,比如:0.5;

android:toXScale-----水平方向的结束值,比如1.2;

android:fromYScale------竖直方向缩放的起始值;

android:toYScale------竖直方向缩放的结束值;

android:pivotX-------缩放的轴点的x坐标,它会影响缩放的效果;

android:pivotY-------缩放的轴点的y坐标,它会影响缩放的效果

<rotate>标签表示旋转动画,对于RotateAnimation,它可以使View具有旋转的动画效果,它的属性的含义如下:

android:fromDegress-----旋转开始的角度,比如0;

android:toDegress-----旋转结束的角度,比如180;

android:pivotX-------旋转的轴点的x坐标;

android:pivotY-------旋转的轴点的y坐标;

<set xmlns:android="http://schemas.android.com/apk/res/android">    <rotate        android:duration="500"        android:fromDegrees="0"        android:interpolator="@android:anim/accelerate_interpolator"        android:pivotX="50%"        android:pivotY="50%"        android:repeatCount="0"        android:toDegrees="360" /></set>  
<alpha>标签表示透明度动画,对应AlphaAnimation,它可以改变View的透明度,它的属性如下:

android:fromAlpha------表示透明度的起始值,比如0.1;

android:toAlpha--------表示透明度的结束值,比如1。

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android">    <alpha        android:duration="500"        android:fromAlpha="1"        android:toAlpha="0" /></set>

View动画还有一些常用的属性,如:

android:duration-----动画的持续时间;

android:fillAfter-------动画结束以后View是否停留在结束位置,true表示View停留在结束位置,false则表示不停留;默认为false。

2)、自定义View动画

在实际开发中很少用到自定义View动画。

3)、帧动画

帧动画使顺序播放一组预定义好的图片,类似于电影播放。不同于View动画,系统提供了另外一个类AnimationDrawable来使用帧动画。帧动画使用比较简单,但比较容易引起OOM,所以在使用帧动画时应尽量避免使用过度尺寸较大的图片。

步骤1:在res//drawable/文件夹下创建帧动画的xml文件:

<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@mipmap/im_conversation_ic_audio_right_level1" android:duration="300"/>    <item android:drawable="@mipmap/im_conversation_ic_audio_right_level2" android:duration="300"/>    <item android:drawable="@mipmap/im_conversation_ic_audio_right_level3" android:duration="300"/></animation-list>

步骤2:将上述Drawable作为View的背景并通过Drawable来播放动画即可:

imageView2 = (ImageView) view.findViewById(R.id.image_chat_sound_me);            imageView2.setBackgroundResource(R.drawable.chat_image_sound_me);            AnimationDrawable animation = (AnimationDrawable) imageView2.getBackground();            animation.start();

2、View动画的特殊使用场景

View动画一般作用于View,但也可以有一些特殊的应用场景,比如ViewGroup中可以控制子元素的出场效果;在Activity中实现不同Activity之间的切换效果

1)、LayoutAnimation

LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,这样当它的子元素出场时都会具有这种动画效果。这种效果常常用在ListView上,ListView每个Item都以一定的动画形式出现,其实就是使用LayoutAnimation。

步骤:

①、定义LayoutAnimation

<?xml version="1.0" encoding="utf-8"?><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"    android:animation="@anim/anim_item"    android:animationOrder="normal"    android:delay="0.5" />

②、为子元素指定具体的入场动画

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

③、为ViewGroup指定android:layoutAnimation属性;对于ListView来说,这样ListView的item就具有出场动画了,这种方式适合所有的ViewGroup。

<ListView            android:id="@+id/listview_active_student"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:background="@color/color_bg_page_light_gray"            android:cacheColorHint="@android:color/transparent"            android:descendantFocusability="afterDescendants"            android:divider="@android:color/transparent"            android:dividerHeight="6dp"            android:fadingEdge="none"            android:footerDividersEnabled="false"            android:layoutAnimation="@anim/anim_layout"            android:listSelector="@null"            android:scrollbars="none" />

Activity的切换效果,Fragment切换添加动画

Activity有默认的切换动画,但是这个效果可以自定义,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity(Intent)或者finish()之后调用才能生效。

  <span style="white-space:pre"></span>Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class);                    startActivity(mainIntent);                    finish();                    overridePendingTransition(R.anim.fade_in, R.anim.fade_out);

Fragment也可以添加切换动画,通过FragmentTranslation中的setCustomAnimation()方法来添加切换动画。

3、属性动画

1)、使用属性动画

属性动画可以对任意对象的属性进行动画而不仅仅是View,动画默认时间间隔300ms,默认帧率10ms/帧。可以达到的效果是:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。因此,属性动画几乎是无所不能的,主要对象有这个属性,它都能实现动画效果。可以采用开源动画库nineoldandroids来兼容以前的版本。

比较常用的几个动画类是:ValueAnimation、ObjectAnimation和AnimationSet。其中ObjectAnimator继承自ValueAnimator、AnimatorSet是动画集合,可以定义一组动画,它们的使用及其简单。

改变一个对象(myObject)的translationY属性,让其沿着Y轴上平移一段距离:它的高度,该动画在默认时间内完成,动画的完成时间是可以定义的。想要更加灵活的效果,还可以定义插值器和估值算法,但是一般来说都不需要自定义,系统预置的就够用。代码示例:

①、引导页的立即体验,从屏幕右边水平向左移:

ObjectAnimator translationX = ObjectAnimator.ofFloat(mStartView, "translationX", 500f, 0f);                        translationX.setRepeatCount(0);                        translationX.setDuration(1000);                        translationX.start();
②、引导页的跳过,放大缩写:

ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(mJumpView, "scaleX", 1.2f, 0.7f, 1.2f);        ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(mJumpView, "scaleY", 1.2f, 0.7f, 1.2f);        scaleXAnim.setRepeatCount(-1);        scaleYAnim.setRepeatCount(-1);        scaleYAnim.setRepeatMode(ObjectAnimator.RESTART);        scaleXAnim.setRepeatMode(ObjectAnimator.RESTART);        AnimatorSet scaleSet = new AnimatorSet();        scaleSet.playTogether(scaleXAnim, scaleYAnim);        scaleSet.setDuration(3000);        scaleSet.start();

③、改变一个对象的背景色属性,典型的情形是改变View的背景色:

 ValueAnimator colorAnimator = ObjectAnimator.ofInt(tv_aboutus, "backgroundColor",                0XFFFF8080, 0xFF8080FF);        colorAnimator.setDuration(1000);        colorAnimator.setEvaluator(new ArgbEvaluator());        colorAnimator.setRepeatCount(ValueAnimator.INFINITE);        colorAnimator.setRepeatMode(ValueAnimator.REVERSE);        colorAnimator.start();
属性动画除了通过代码实现以外,还可以通过xml来定义。属性动画需要定义在res/animator目录下。但在实际开发中建议使用代码来实现属性动画,比较简单。很多时候一个属性的起始值时无法提前确定的。

2)、理解插值器和估值器

TimeInterpolator中文翻译为时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比。系统预置的有:LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)和DecelerateInterpolator(减速插值器:动画越来越慢)等。

TypeEvaluator中文翻译为类型估值算法,也叫估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有InterEvaluator(针对整形属性)、FloatEvaluator(针对浮点型属性)和ArgEvaluator(针对Color属性)。

属性动画中的插值器和估值器很重要,它们是实现非匀速动画的重要手段。

属性动画要求对象的该属性有set方法和get方法(可选)。插值器和估值算法除了系统提供的外,我们还可以自定义。实现方式很简单,因为插值器和估值算法都是一个接口,且内部都只有一个方法,只要派生一个类实现接口就可以了,然后就可以做出千奇百怪的动画效果。具体一点就是:自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值算法需要实现TypeEvaluator。另外就是如果要对其他类型(非int、float、Color)做动画,那么必须要自定义类型估值算法。

3)、属性动画的监听器

属性动画提供了监听器用于监听动画的播放过程。主要有如下两个接口:AnimatorUpdateListener和AnimatorListener,后者是前者的适配器类。

 /**     * <p>An animation listener receives notifications from an animation.     * Notifications indicate animation related events, such as the end or the     * repetition of the animation.</p>     */    public static interface AnimatorListener {        /**         * <p>Notifies the start of the animation.</p>         *         * @param animation The started animation.         */        void onAnimationStart(Animator animation);        /**         * <p>Notifies the end of the animation. This callback is not invoked         * for animations with repeat count set to INFINITE.</p>         *         * @param animation The animation which reached its end.         */        void onAnimationEnd(Animator animation);        /**         * <p>Notifies the cancellation of the animation. This callback is not invoked         * for animations with repeat count set to INFINITE.</p>         *         * @param animation The animation which was canceled.         */        void onAnimationCancel(Animator animation);        /**         * <p>Notifies the repetition of the animation.</p>         *         * @param animation The animation which was repeated.         */        void onAnimationRepeat(Animator animation);    }
AnimatorUpdateListener:

/**     * Implementors of this interface can add themselves as update listeners     * to an <code>ValueAnimator</code> instance to receive callbacks on every animation     * frame, after the current frame's values have been calculated for that     * <code>ValueAnimator</code>.     */    public static interface AnimatorUpdateListener {        /**         * <p>Notifies the occurrence of another frame of the animation.</p>         *         * @param animation The animation which was repeated.         */        void onAnimationUpdate(ValueAnimator animation);    }
4)、对任意属性做动画

如果随便传递一个属性过去,轻则没动画,重则程序直接crash!

属性动画的原理:属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据外界传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切地说是随着时间的推移,所传递的值越来越接近最终值。

建议:

①、给你的对象加上get和set方法,如果你有权限的话;

②、用一个类来包装原始对象,间接为其提供get和set方法;

③、采用ValueAnimator,监听动画过程,实现属性的变化。

4、使用属性动画的注意事项

1)、OOM问题:主要出现在帧动画中,当图片数量较多且图片较大时极易出现OOM;这个在实际开发中尤其要主要,尽量避免使用帧动画。

2)、内存泄露:在属性动画中有一个无限循环的动画,这类动画需要在Activity退出时及时停止。

3)、兼容性问题

4)、View动画的问题:View动画使对View的影像做动画,并不是真正地改变View的状态,调用view.clearAnimation()清除View动画。

5)、不要使用px:适配

6)、动画元素的交互

7)、硬件加速:使用动画的过程中,建议开启硬件加速,这样会提高动画的流程性。

0 0