Animation动画相关知识点

关于 Animation 的一些回顾和总结

关于Animation 和 Animator

Animation 是我们经常用到的一些动画,包括帧动画和补间动画,而 AnimatorAndroid 3.0 的时候推出的动画框架,也称为属性动画

版本兼容 实现效率 适用性 是否产生内存泄漏 使用效果
Animation 可兼容Android3.0以下的版本 直接通过代码对矩阵进行处理 仅对View对象有用 不会 假的移动
Animator 无法兼容,也没有向下兼容的support包 通过设置对象的setter,getter方法,来达到动画目的,使用了java反射机制,可用于任意对象,效率低于Animation 任意对象(但是需要有get/set方法) 可能会,当设置为无限循环时,如果在Activity退出时没有及时将动画停止,属性动画会导致Activity无法释放而导致内存泄漏。 真的位置变换

关于动画的基本使用

  • Animation 相关动画的使用

    帧动画

    一般我们使用帧动画都是采取xml定义的方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // yun_anim.xml
    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item
    android:drawable="@mipmap/app_loading0"
    android:duration="150" />
    <item
    android:drawable="@mipmap/app_loading1"
    android:duration="150" />
    <item
    android:drawable="@mipmap/app_loading2"
    android:duration="150" />
    <item
    android:drawable="@mipmap/app_loading3"
    android:duration="150" />

    </animation-list>
    //将它定义成一个drawable,这样引用
    <ImageView
    android:id="@+id/img_progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/yun_anim" />

    补间动画

    包括一些平移(Translate),旋转(Rotate),透明度(Alpha),缩放动画(Scale),使用都差不多,可以在xml中创建使用也可以动态创建使用。

    xml 中类似于这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //这是一个动画集合
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
    android:duration="200"
    android:fromYDelta="100%p"
    android:toYDelta="0" />
    </set>
    //使用xx布局文件的名称
    Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.xx);
    iv.startAnimation(translateAnimation);

    java 代码设置:

    1
    2
    3
    4
    //位移动画,相应还有旋转其它类似
    Animation animation = new TranslateAnimation(0,100,0,100)
    translateAnimation.setDuration(3000);
    iv.startAnimation(translateAnimation);

    属性动画

    ValueAnimator 是属性动画的一个核心类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
    anim.setDuration(300);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    float currentValue = (float) animation.getAnimatedValue();
    Log.d("TAG", "cuurent value is " + currentValue);
    }
    });
    anim.start()

    ObjectAnimator

    1
    2
    3
    4
    5
    6
    7
    8
    //透明度的变化,还可以位移啥的
    ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "alpha", 1f, 0f, 1f);
    animator.setDuration(5000);
    animator.start();
    ------------------------------
    ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "rotation", 0f, 180f);
    animator.setDuration(5000);
    animator.start();

官方一张图:

image.png

ValueAnimator 是属性动画很重要的一个类,其中 ObjectAnimator 继承于 ValueAnimator ..

问题:那 ValueAnimator 到底是怎样实现初始值平滑过渡到结束值的呢?

这个是由 TypeEvaluatorTimeInterpolator 共同决定的。

具体来说:TypeEvaluator 决定了从初始值过度到结束值过度的方式。TimeInterpolator 决定了动画从初始值过渡到结束值的节奏。

有个例子很恰当:你每天上班去公司,是选择地铁出行还是公交,还是骑行,选择从出发地到目的地的一种抵达方式,这个是 TypeEvaluator, 假如你选择骑行,是均速骑行到目的地还是先加速后减速,还是一开始慢后来快,这个就是 TimeInterpolator 决定的。

TypeEvaluator 确定运动轨迹

一般来说,要定义运动轨迹,需要实现 TypeEvaluator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class PointEvaluator implements TypeEvaluator {

/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values 动画当前进行的进度
* @param startValue The start value.开始值
* @param endValue The end value.结束值
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.线性
*/
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
//自定义轨迹路线,假如我们做一个线性运动
return new Point((int)(startValue.getX()+endValue.getX()*fraction),
(int)(startValue.getY()+endValue.getY()*fraction));
}
}

使用的时候:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Point startP = new Point(0,0);
Point endP = new Point(500,500);
ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointEvaluator(), startP, endP);
valueAnimator.setDuration(5000);
valueAnimator.setRepeatCount(10);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Point currentPoint = (Point) animation.getAnimatedValue();
iv.setX(currentPoint.getX());
iv.setY(currentPoint.getY());
current.setX(130+currentPoint.getX());
current.setY(currentPoint.getY());

current.setText("");
current.setText("x="+currentPoint.getX()+" y="+currentPoint.getY());

}
});
valueAnimator.start();

这样我们就完成了动画轨迹的定义。

例如我们来一个最简单的线性运动:

one.jpg

two.jpg

TimeInterpolator

前面说过,这个是用来控制动画从开始到结束的节奏的。Android 自己提供了几个自带的 Interpolator,当然同时也可以自定义实现。

image.png

-------------本文结束感谢您的阅读-------------