Android中的属性动画理解

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



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值