您的位置:首页 > 移动开发 > Android开发

Android:动画系统

2015-09-16 16:35 495 查看
目前Android上有三种动画实现,分别为tweened animation、frame-by-frame animation以及3.0后新增的property animation。

tweened animation

简介

tweened animation可以实现四种动画效果,分别为:

平移,对应translation

旋转,对于rotate

缩放,对应scale

淡化,对于alpha

几种动画常用的方法有:

public void setDuration(long durationMillis)

public void setFillAfter(boolean fillAfter)

public void setRepeatCount(int repeatCount)

public void setRepeatMode(int repeatMode)

public void setStartOffset(long startOffset)

public void setInterpolator(Interpolator i)

public void setAnimationListener(AnimationListener listener)



其中上述的倒数第二个方法是设置动画变换速率/效果的意思,常见的有:

AccelerateDecelerateInterpolator

在动画开始与结束的时候减速,在中间的时候加速

AccelerateInterpolator

在动画开始的时候减速,然后开始加速

DecelerateInterpolator

在动画开始的时候加速,然后开始减速

LinearInterpolator

在动画的以均匀的速率改变

CycleInterpolator

动画循环播放特定的次数,速率改变沿着正弦曲线

BounceInterpolator

撞击模式



如果需要同时实现几种动画效果,则使用
AnimationSet


构造方法

Translate

public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)

从偏移后的from偏移至to(偏移量from-to)像素,单位是像素。纵向总像素包括(系统状态栏、TitleBar、content)。

public TranslateAnimation (int fromXType, float fromXValue, int toXType, float toXValue,

int fromYType, float fromYValue, int toYType, float toYValue)

本质上和上述一样,只是给个参考值来计算像素,比如当type=Relative_To_Self时,value=1.0f相当于本身控件的长度。

Rotate

public RotateAnimation (float fromDegrees, float toDegrees)

参考点为左上角,to-from>0为顺时针。

public RotateAnimation (float fromDegrees, float toDegrees, float pivotX, float pivotY)

参考点为左上角的偏移像素值

public RotateAnimation (float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

本质上和上述一样,只是给个参考值来计算像素。

Scale

public ScaleAnimation (float fromX, float toX, float fromY, float toY)

参考点为左上角

public ScaleAnimation (float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)

参考点为左上角的偏移像素值

public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

本质上和上述一样,只是给个参考值来计算像素。

放大时从参考点往外放大,缩小时向参考点的方向缩小。

上述的value为
负号
时即减去像素值~~

Alpha

public AlphaAnimation (float fromAlpha, float toAlpha)

实例

1、java代码方式

[code]button = (Button) findViewById(R.id.button);
// 水平移动至父控件的一半
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);
// 从自身中点位置从0放大至1
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1f, 0, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 淡化效果从0增加至1
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1f);
// 动画集
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
// 设置动画时间
animationSet.setDuration(2000);
// 设置效果
animationSet.setInterpolator(new BounceInterpolator());
// 动画完毕后停留
animationSet.setFillAfter(true);
button.startAnimation(animationSet);


2、xml定义方式,放在anim目录下,anim/test.xml

[code]<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:fillAfter="true"
    android:interpolator="@android:anim/bounce_interpolator"
    android:shareInterpolator="true">

    <translate
        android:fromXDelta="0"
        android:toXDelta="50%p" />

    <scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

</set>


[code]Animation animation = AnimationUtils.loadAnimation(this, R.anim.test);
button.startAnimation(animation);


LayoutAnimation

ViewGroup的子控件动画

1、java代码方式

[code]// 获取动画对象,这里也可以看到xml定义动画的方式有利于复用。
Animation animation=AnimationUtils.loadAnimation(this, R.anim.test);
// 获取LayoutAnimationController对象
LayoutAnimationController lac=new LayoutAnimationController(animation);
// 设置顺序
lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
// 设置间隔
lac.setDelay(1f);
// viewgroup设置动画效果
viewgroup.setLayoutAnimation(lac);


2、xml定义方式

在anim目录下建立一个xml文件,layout.xml,指定其动画xml@animation,并将其设置在viewgroup底下属性

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


[code]<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutAnimation="@anim/layout"
    android:orientation="vertical">
    ...
</LinearLayout>


frame-by-frame animation

顾名思义,就在一帧一帧的图片构成动画,所以需要放入几张构成连贯动画的图片,比如在drawable目录底下放入walk1、…、walk6图片,然后新建一个walk.xml文件。

[code]<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/walk1"
        android:duration="200" />

    <item
        android:drawable="@drawable/walk2"
        android:duration="200" />

    <item
        android:drawable="@drawable/walk3"
        android:duration="200" />

    <item
        android:drawable="@drawable/walk4"
        android:duration="200" />

    <item
        android:drawable="@drawable/walk5"
        android:duration="200" />

    <item
        android:drawable="@drawable/walk6"
        android:duration="200" />

</animation-list>


最后用一个ImageView作为载体,将动画效果实现在此ImageView上即可。

[code]iv.setBackgroundResource(R.drawable.walk); // 也可在xml中指定background属性
AnimationDrawable animationDrawable = (AnimationDrawable) iv.getBackground();
animationDrawable.start();


property animation

tweened animation的主要缺陷:

只能用于view上

只改变了view的显示效果,而不会真正去改变View的属性。比如说一个Button平移后,实际上Button依然在原来的位置,而不是实现平移动画效果后的位置。

ValueAnimator

这个类是整个属性动画的核心,它的核心功能就是监听值的变化,然后可以根据这个值来改变控件的属性,最后达到动画效果。我们只需要将初始值和结束值提供给ValueAnimator,设置时长,那么ValueAnimator就会帮我们完成从初始值到结束值的变化效果。

它的接口也和Animation很类似。

[code]// public static ValueAnimator ofFloat(float... values),参数为可变参数
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 240f);
valueAnimator.setDuration(2000);
// AnimatorUpdateListener监听值的变化
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float animatedValue = (float) animation.getAnimatedValue();
        button.setTranslationY(animatedValue);
    }
});
valueAnimator.start();


ObjectAnimator

ObjectAnimator继承自ValueAnimator,它的效果其实就是在ValueAnimator的基础上,监听数值变化,然后改变第二个参数。由此也可以推测出,button这个控件是有translationX/alpha/rotate等的getter/setter方法的。和上面例子对应的效果。

[code]ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "translationX", 0f, 240f);
objectAnimator.setDuration(2000);
objectAnimator.start();


需要注意的是,rotate、scale两个操作的参考点和tweened有所不同,具体实际一下就可以知道了。

AnimatorSet

在上面两个例子的基础上

[code]AnimatorSet set = new AnimatorSet();
set.play(valueAnimator).with(objectAnimator); // 还有before、after
set.setDuration(3000);


TypeEvaluator

简单来说,TypeEvalator就是告诉动画系统如何从初始值过度到结束值。其实上面例子中的
public static ValueAnimator ofFloat(float... values)
内置了FloatEvaluator,同理ofInt则内置了IntEvaluator。

[code]public class FloatEvaluator implements TypeEvaluator<Number> {

    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}


如果要在我们自己的对象上面实现过渡效果,显然需要自定义一个TypeEvaluator,然后传进ofObject方法。

比如有个类人,我们需要实现其年龄的过渡效果,则需要定义一个TypeEvaluator。

[code]private class Human {
    int age;

    public Human(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Human{" +
                "age=" + age +
                '}';
    }
}


[code]private class HumanEvaluator implements TypeEvaluator<Human> {
    @Override
    public Human evaluate(float fraction, Human startValue, Human endValue) {
        int age = (int) (startValue.getAge() + fraction * (endValue.getAge() - startValue.getAge()));
        return new Human(age);
    }
}


[code]ValueAnimator valueAnimator = ValueAnimator.ofObject(new HumanEvaluator(), new Human(30), new Human(100));
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.e("TAG", ((Human) animation.getAnimatedValue()).toString());
    }
});
valueAnimator.start();


根据前面所说,ObjectValue会通过setter/getter改变其属性。注意与上例区别,上例演示ofObject方法、此例演示ObjectAnimator的操作本质。

[code]final Human human = new Human(30);
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(human, "age", 30, 100);
objectAnimator.setDuration(2000);
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.e("tag", human.toString());
    }
});
objectAnimator.start();


小结:

1、ValueAnimator实现值的过渡,ofInt、ofFloat内置IntEvaluator、FloatEvaluator所以直接传入过渡值即可;ofObject方法需要自定义TypeEvaluator,表明过渡效果。

2、ObjectAnimator实现
具体对象的字段的变化
,需要传进
target对象
以及
需要过渡的字段
,ofInt、ofFloat方法内置IntEvaluator、FloatEvaluator所以直接传入过渡值即可,ofObject方法需要自定义TypeEvaluator,表明过渡效果。

其他

以下三个问题刚好鸿洋的这篇文章里都有涉及

/article/1336248.html

1、ViewPropertyAnimator,3.1引入,直接在view.animate()方法返回这个对象,然后就可以直接进行动画操作。

2、xml实现属性动画

3、LayoutTransition

总结

1、三种动画方式都可以使用纯Java代码或者XML定义的方式来实现;

2、属性动画是真正值的改变,而tweened动画只是视图的改变。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: