Android(Animation框架)动画原理:

控制的是整个View,原理:每次绘制视图时View所在的ViewGroup中的drawChild()获取该View的Animation的Transformation值,然后调用canvas.concat(transfromToApply.getMatrix()),通过矩阵换算完成动画帧,如果没有完成,就继续调用invalidate(),启动下次绘制来驱动动画,直到完成动画的绘制。

动画分类:
帧动画
补间动画
属性动画

动画常见展现形式:
透明度
旋转
缩放
位移


一、帧动画:

原理:通过顺序播放一系列图像从而产生动画效果(ps:如果图片过大就会导致OOM)
使用:
在drawable文件中新建文件:

<?xml version="1.0" encoding="utf-8"?>
<!--  android:oneshot="false"  false动画循环执行 true动画执行一次-->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/img_1" android:duration="500"/>
<item android:drawable="@drawable/img_2" android:duration="500"/>
<item android:drawable="@drawable/img_3" android:duration="500"/>
<item android:drawable="@drawable/img_4" android:duration="500"/>
</animation-list>

代码调用:

imageView = (ImageView) findViewById(R.id.img);          imageView.setImageResource(R.drawable.frame_anim);
AnimationDrawable drawable = (AnimationDrawable) imageView.getDrawable();
drawable.start();

二、补间动画:
原理:通过对场景里的对象不断做图像变换从而产生动画效果(View动画的作用对象是View)

种类:
ScaleAnimation
RotateAnimation
Transformation
AlphaAnimation

xml用法:
在res/anim文件中新建文件:

<?xml version="1.0" encoding="utf-8"?><!-- android:shareInterpolator="false"  表示集合中的动画是否共享同一个插值器-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
                    android:shareInterpolator="false">
                    <alpha
                        android:fromAlpha="float"
                        android:toAlpha="float" />
                    <scale
                        android:fromXScale="float"
                        android:fromYScale="float"
                        android:pivotX="float"
                        android:pivotY="float"
                        android:toXScale="float"
                        android:toYScale="float" />
                    <translate
                        android:fromXDelta="float"
                        android:fromYDelta="float"
                        android:toXDelta="float"
                        android:toYDelta="float" />
                    <rotate
                        android:fromDegrees="float"
                        android:pivotX="float"
                        android:pivotY="float"
                        android:toDegrees="float" />
                </set>

代码调用:

imageView = (ImageView) findViewById(R.id.img);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_animation);
imageView.startAnimation(animation);

代码使用:自行google

监听事件:

public static interface AnimationListener {
void onAnimationStart(Animation animation);
void onAnimationEnd(Animation animation);
void onAnimationRepeat(Animation animation);
                                          }

三、属性动画:

原理:通过动态改变对象的属性从而达到动画效果(API 11新特性,不能向下兼容,故有nineoldandroids兼容库)

属性动画除了视图动画的四种,还可以实现刚加绚丽的动画,视图动画主要依于Animation抽象类,而属性动画依于Animator抽象类,我们看下Animator的扩展类:

android value动画实现 android 动画实现原理_android value动画实现


常用的类就是AnimatorSet 、ObjectAnimator、 ValueAnimator

其中 ValueAnimator 是 ObjectAnimator的基类

xml用法:
在drawable文件中新建文件:

<?xml version="1.0" encoding="utf-8"?><!--android:ordering="sequentially|together" 按顺序播放|一起播放-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
   <animator
        android:duration="100"
        android:interpolator=""
        android:repeatCount=""
        android:repeatMode=""
        android:startOffset=""
        android:valueFrom=""
        android:valueTo=""
        android:valueType=""/>
    <objectAnimator
         android:duration=""
        android:valueType=""
        android:valueTo=""
        android:valueFrom=""
        android:startOffset=""
        android:interpolator=""
        android:pathData=""
        android:propertyName=""
        android:propertyXName=""
        android:propertyYName=""
        android:repeatCount=""
        android:repeatMode=""
        />


</set>

上面的属性值我并没有给出,相信小伙伴大部分都知道,我就不解释了,
代码调用:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.ainmatorset);
        set.setTarget(imageView);
        set.start();

代码用法: 自行Google

插值器&估值器:

TimeInterpolator:时间差值器,根据时间流逝的百分比,来计算当前属性值改变的百分比。

android value动画实现 android 动画实现原理_xml_02


源码中Interpolator接口继承TimeInterpolator

Interpolator的实现类如下:

android value动画实现 android 动画实现原理_android_03


常用的插值器有:

LinearInterpolator(线性插值器:匀速动画)

AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)

DecelerateInterpolator(减速插值器:动画越来越慢)

。。。。。。。等TypeEvaluator:类型估值算法,又叫估值器。根据当前属性改变的百分比来计算改变后的属性值。

常用的估值器:

android value动画实现 android 动画实现原理_属性动画_04

属性动画中的插值器&估值器是实现非匀速动画的重要手段。

属性动画监听:

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);

    }
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);
    }
AnimatorListenerAdapter是系统为AnimatorListener提供的一个适配器类便于开发者调用需要的方法

属性动画满足的条件:
1、属性动画要求动画作用的对象提供该属性的get和set方法(如果不满足直接Crash)。
2、对象的set方法对属性所做的改变必须通过某种方法反映出来,比如UI的改变(如果不满足,动画无效,不会Crash);
如果在我们开发中以上条件有一个或多个不满足怎么办呢?
官方有三种解决方案:

  • 如果有权限,给你的对象加上get&set方法(逗我-_-);
  • 用一个来包装对象,间接提供get&set方法(靠谱+_+);
  • 采用ValueAnimator,监听动画过程,自己是实现属性的改变;
    ValueAnimator:
    本身不作用于任何对象,也就是说直接使用,没有任何动画效果,但它可以对一个值做动画,然后我们监听其过程,动画过程中修改对象属性值,这样就相当于我们的对象做了动画。

四、自定义View动画:
Animation是抽象类,我们只需要重写它的applyTransformation()和initialize(),在 initialize()做一些初始化操作,在applyTransformation()
进行相应的矩阵变换。


五、LayoutAnimation(布局动画):
最简单的布局动画就是在ViewGroup加上android:animateLayoutChanges=”true”
当ViewGroup添加View时候,子View会呈现逐渐显示的过度动画,这是Android默认的过度效果。
作用于ViewGroup容器,比如RecyclerView加上这样的动画,那么RecyclerView的每个item就会有一个出场效果。
用法:在res/anim文件中新建文件

<?xml version="1.0" encoding="utf-8"?>
<!--android:animationOrder="normal|random|reverse" 顺序|随机|反转
android:delay="0.5"   0.5表示子元素入场动画的周期的0.5倍 ps:周期300ms  延迟150ms
android:animation="@anim/set_animation" xml定义的动画 -->
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
            android:delay="0.5"
            android:animationOrder="normal"
            android:animation="@anim/set_animation"
            />

布局文件用法:

<android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layoutAnimation="@anim/anim_layout"

代码用法:

Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_animation);
LayoutAnimationController controller=new LayoutAnimationController(animation);
controller.setDelay(0.5f);      controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listview.setLayoutAnimation(controller);

代码写法:

ScaleAnimation animation = new ScaleAnimation(0, 1, 0, 1);
animation.setDuration(500);
LayoutAnimationController controller = new LayoutAnimationController(animation, 0.5f);
controller.setOrder(LayoutAnimationController.ORDER_RANDOM);
listView.setLayoutAnimation(controller);

六、Activity的切换动画:

overridePendingTransition(int enterAnim, int exitAnim);
enterAnim:进场动画
exitAnim :出场动画
注意要在activity执行startActivity()或者finish()之后调用

Fragment也可以添加动画FragmentTransaction中的setCustomAnimations
(@AnimRes int enter,@AnimRes int exit);

使用动画的注意事项:
1、OOM:
这个问题主要出现在帧动画,当图片资源过多且大时候极易出现OOM。所以尽量避免使用帧动画。
2、内存泄漏:
在属性动画中有一类无限循环动画,这类动画需要在Activity退出时及时停止动画,否则会导致Activity无法释放导致内存泄漏,但View动画不会。
3、兼容性问题
动画在android3.0下有兼容性问题,要做好适配
4、View动画问题
View动画是对View的影像做动画,并不是真正的改变View的状态,因此有时候出现动画完成后View无法隐藏的现象,即setVisibility(View.GONE)失效,通常这样解决:view.clearAnimation()清楚View动画即可。
5、硬件加速
使用动画时候建议开启硬件加速,提高动画的流畅性。