Android中的属性动画理解

来源:互联网 发布:旧金山州立大学 知乎 编辑:程序博客网 时间:2024/05/15 02:08

Android中有补件动画,帧动画和属性动画这几种常见动画。属性动画是3.0系统后推出的比较强大的动画。可以实现生活中大多数常见的动画功能。最近学习,用到了属性动画,结合源码和一些参考做一个记录。

1.基本使用

属性动画中常用到类ValueAnimator,ObjectAnimator,属性动画就是通过改变对象的属性实现动画,这两个类完成了对象的属性从初始值到结束的值的变化。

常用的方法:ofFloat(),ofInt(),ofObject();等。这些方法都有很多不同的重载方法,提供不同的参数实现差异的功能。

其中有一个:ValueAnimator bizerAnimator = ObjectAnimator.ofObject(typeEvalautor, param, param,param);这个需要传入一个估值器对象(TypeEvaluator)

其他方法:

  bizerAnimator.setEvaluator();//设置一个估值器  bizerAnimator.setRepeatCount();//设置重复执行次数  bizerAnimator.setRepeatMode();//设置动画重复的模式  bizerAnimator.setTarget();//设置动画添加一个对象  bizerAnimator.setInterpolator();//设置一个插值器
这里插值器和估值器是实现一些复杂效果的关键。

基本使用举例:

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,1f);        valueAnimator.setDuration(500);        valueAnimator.start();
一个基本的用法就是三行代码,实现500毫秒从0到1的变化;其实还可以传入多个参数,这个ofFloat()方法参数是边长参数。

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,0.6f,0.2f,1f);        valueAnimator.setDuration(500);        valueAnimator.start();
上面实现了从0到0.6到0.2再到1的变化。

ObjectAnimator类:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"translationX",0f,200f,0f);                objectAnimator.setDuration(2000);                objectAnimator.start();
对一个ImageView 实现从起始位置到200px在到原始位置的变化,对应的:
"translationX"
是ImageView 的一个属性,这个属性在ImageView 中有个对应的set方法:

imageView.setTranslationX(0);
这里需要注意的一点就是:在对一个对象进行操作的时候,第一个参数是对象示例,第二个参数一定是对应对象的一个属性并且有一个set方法去设置这个属性。动画执行过程就是通过这个属性设置值的。

2.组合使用

组合使用就是把不同的动画效果放一起执行,可以是先后执行,也可以同时执行,这是实现一些复杂效果的关键。组合使用通过AnimatorSet 来组合。

比如对上的图片添加第一个移动,透明度变化和旋转三种动画,组合执行:

 AnimatorSet animatorSet = new AnimatorSet();                ObjectAnimator translation = ObjectAnimator.ofFloat(imageView,"translationX",0f,300f,0f);                ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView,"alpha",1f,0f,1f);                ObjectAnimator rotationY = ObjectAnimator.ofFloat(imageView,"rotationY",0f,360f);                //animatorSet.playSequentially(translation,alpha,rotationY);//按顺序执行位置移动,透明度变化,和旋转三个动画效果。                //animatorSet.play(translation).with(alpha).before(rotationY);//执行translation同时执行alpha 设置,在执行rotationY之前。                animatorSet.playTogether(translation,alpha,rotationY);//三个同时执行                animatorSet.setDuration(3000);                animatorSet.start();
以上代码创建了三个通话效果,通过不同的方法组合不同的执行效果。
知道了这些,我们还可以通过操作其他的对象属性作出其他的效果来。

属性动画的基本使用就是这些,如果代码操作不方便还可以写xml,在项目中使用。直接在代码中加载设置执行。

<set xmlns:android="http://schemas.android.com/apk/res/android">    <objectAnimator        android:duration="1000"        android:propertyName="translationX"        android:valueFrom="0dp"        android:valueTo="100dp"        android:valueType="floatType" />    <objectAnimator        android:duration="1000"        android:propertyName="alpha"        android:valueFrom="0"        android:valueTo="1"        android:valueType="floatType"/>    <!--<objectAnimator-->        <!--android:duration="1000"-->        <!--android:propertyName="translationX"-->        <!--android:valueFrom="100dp"-->        <!--android:valueTo="0dp"-->        <!--android:valueType="floatType" />--></set>
加载执行:

 Animator animator = AnimatorInflater.loadAnimator(this,R.animator.animator1);                animator.setTarget(imageView);                animator.start();
仔细的看看xml代码,其实没有直接java创建动画方便,java中属性在一个动画可以重复操作如:位置移动,从左到右,在到左。

3.实际应用

如果还需要其他的复杂效果就要通过我们自定义来实现了。比如网络中的一些弹跳效果,水波效果等,这里了解一些概念。

估值器

所谓估值器从名称上一直没有理解明白。实际就是实现一个逻辑处理的方法。

估值器实现了一个接口重写了evaluate()方法。

public interface TypeEvaluator<T> {    /**     * 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.     */    public T evaluate(float fraction, T startValue, T endValue);}

看几个个系统提供的估值器代码:

public class IntEvaluator implements TypeEvaluator<Integer> {    /**     * 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 * (v1 - v0)</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; should be of type <code>int</code> or     *                   <code>Integer</code>     * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>     * @return A linear interpolation between the start and end values, given the     *         <code>fraction</code> parameter.     */    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {        int startInt = startValue;        return (int)(startInt + fraction * (endValue - startInt));    }}
上面是一个整数估值器,evaluate();方法就是进行一个计算处理在返回去。

public class PointFEvaluator implements TypeEvaluator<PointF> {    private PointF mPoint;    public PointFEvaluator() {    }    public PointFEvaluator(PointF reuse) {        mPoint = reuse;    }    /**     * This function returns the result of linearly interpolating the start and     * end PointF values, with <code>fraction</code> representing the proportion     * between the start and end values. The calculation is a simple parametric     * calculation on each of the separate components in the PointF objects     * (x, y).     *     * <p>If {@link #PointFEvaluator(android.graphics.PointF)} was used to construct     * this PointFEvaluator, the object returned will be the <code>reuse</code>     * passed into the constructor.</p>     *     * @param fraction   The fraction from the starting to the ending values     * @param startValue The start PointF     * @param endValue   The end PointF     * @return A linear interpolation between the start and end values, given the     *         <code>fraction</code> parameter.     */    @Override    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {        float x = startValue.x + (fraction * (endValue.x - startValue.x));        float y = startValue.y + (fraction * (endValue.y - startValue.y));        if (mPoint != null) {            mPoint.set(x, y);            return mPoint;        } else {            return new PointF(x, y);        }    }}
PointFEvaluator 中evaluate()方法对两个PointF进行处理,最后返回。从上面看,估值器就是对指定的一些参数按照我们的需求,重新处理生成一个新的参数给动画执行。

插值器:

估值器也是实现了一个接口和方法。

public interface TimeInterpolator {    /**     * Maps a value representing the elapsed fraction of an animation to a value that represents     * the interpolated fraction. This interpolated value is then multiplied by the change in     * value of an animation to derive the animated value at the current elapsed animation time.     *     * @param input A value between 0 and 1.0 indicating our current point     *        in the animation where 0 represents the start and 1.0 represents     *        the end     * @return The interpolation value. This value can be more than 1.0 for     *         interpolators which overshoot their targets, or less than 0 for     *         interpolators that undershoot their targets.     */    float getInterpolation(float input);}
系统提供了一些常用的插值器:

线性插值器,让动画成线性运动执行。对于接口的方法getInterpolation()直接返回数据,没有处理。

public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {    public LinearInterpolator() {    }    public LinearInterpolator(Context context, AttributeSet attrs) {    }    public float getInterpolation(float input) {        return input;    }    /** @hide */    @Override    public long createNativeInterpolator() {        return NativeInterpolatorFactoryHelper.createLinearInterpolator();    }}
加速插值器,动画逐渐加速。从代码看,getInterpolation()方法返回值是一个进行了乘法或者多次幂函数计算,从数学上说这就是一个幂函数曲线加速。

Math.pow(input, mDoubleFactor);

public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {    private final float mFactor;    private final double mDoubleFactor;    public AccelerateInterpolator() {        mFactor = 1.0f;        mDoubleFactor = 2.0;    }    /**     * Constructor     *     * @param factor Degree to which the animation should be eased. Seting     *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above     *        1.0f  exaggerates the ease-in effect (i.e., it starts even     *        slower and ends evens faster)     */    public AccelerateInterpolator(float factor) {        mFactor = factor;        mDoubleFactor = 2 * mFactor;    }    public AccelerateInterpolator(Context context, AttributeSet attrs) {        this(context.getResources(), context.getTheme(), attrs);    }    /** @hide */    public AccelerateInterpolator(Resources res, Theme theme, AttributeSet attrs) {        TypedArray a;        if (theme != null) {            a = theme.obtainStyledAttributes(attrs, R.styleable.AccelerateInterpolator, 0, 0);        } else {            a = res.obtainAttributes(attrs, R.styleable.AccelerateInterpolator);        }        mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f);        mDoubleFactor = 2 * mFactor;        setChangingConfiguration(a.getChangingConfigurations());        a.recycle();    }    public float getInterpolation(float input) {        if (mFactor == 1.0f) {            return input * input;        } else {            return (float)Math.pow(input, mDoubleFactor);        }    }    /** @hide */    @Override    public long createNativeInterpolator() {        return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor);    }
通过上述系统代码的查看我们大致了解了,插值器就是通过一些数学计算,让当前时间的动画值改变,从而达到一定效果。


总的来说,估值器是处理了动画当前的数据,而插值器就对当前执行速度操作,达到一定效果。后边在对实际的自定义做练习。


参考资料:

http://www.jianshu.com/p/02deec7bf8f0

http://www.cnblogs.com/mengdd/p/3346003.html



原创粉丝点击