Android-Property 动画自定义TypeEvaluator

    如果想根据某个属性TYPE来实现动画,但是这个Type又不是Android系统内置的,这个时候就需要创建一个自己的evaluator来实现了,并且新创建的type必须实现接口TypeEvaluator。Android系统内置的type有int,float和color,他们对应的evaluator是IntEvaluator、FloatEvaluator和ArgbEvaluator。接口TypeEvaluator内只有一个方法,用来计算要实现动画属性的值。    
 
 
/**
 * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
 * allow developers to create animations on arbitrary property types, by allowing them to supply
 * custom evaluators for types that are not automatically understood and used by the animation
 * system.
 *
 * @see ValueAnimator#setEvaluator(TypeEvaluator)
 */
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);

}

先看看Android系统内置FloatEvaluator是怎么弄的:
 
 
public class FloatEvaluator implements TypeEvaluator<Number> {
/**
     * 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>float</code> or
     *                   <code>Float</code> 
* @param endValue   The end value; should be of type <code>float</code> or <code>Float</code>
* @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
还是举个例子来测试一下,先看下面图中的效果:

这个动画在Android-Property Animation(属性动画)中就实现过了,当时是这么实现的:
 
 
private void startValueAnimation(){
    if(mValueAnimator == null){
        mValueAnimator = ValueAnimator.ofFloat(0, 500);
    }
    mValueAnimator.setInterpolator(new AnticipateInterpolator());
    mValueAnimator.setTarget(mImageView);
    mValueAnimator.setDuration(3000);
    mValueAnimator.setRepeatCount(1);
    mValueAnimator.start();
    mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
	    //同时设置X,Y 两个属性
            mImageView.setTranslationX((Float) animation.getAnimatedValue());
            mImageView.setTranslationY((Float) animation.getAnimatedValue());
        }
    });
}

在动画update的时候同时更新View的X和Y属性。此外, 使用AnimatorSet也可以实现这种动画效果。
除了这两种之外还有没有呢?就是自定义一个TypeEvaluator,主要代码如下:
 
 
private void startObjectAnimation() {
    ViewXYHolder viewXYHolder = new ViewXYHolder(mImageView);
    XYHolder startXY = new XYHolder(0f, 0f);
    XYHolder endXY = new XYHolder(500f, 500f);
    ObjectAnimator objectAnimator = ObjectAnimator.ofObject(viewXYHolder, "xY", new XYmEvaluator(), startXY, endXY);
    objectAnimator.setInterpolator(new LinearInterpolator());
    objectAnimator.setDuration(3000);
    objectAnimator.start();
}

public class XYmEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
            XYHolder startXY = (XYHolder) startValue;
            XYHolder endXY = (XYHolder) endValue;
        return new XYHolder(startXY.getX() + fraction * (endXY.getX() - startXY.getX()),
            startXY.getY() + fraction * (endXY.getY() - startXY.getY()));
    }
}

public class XYHolder{
    private float mX;
    private float mY;

    public XYHolder(float x, float y) {
    mX = x;
    mY = y;
}

public float getX() {
    return mX;
}

public void setX(float x) {
    mX = x;
}

public float getY() {
    return mY;
}

public void setY(float y) {
    mY = y;
    }
}

public class ViewXYHolder{
    private View imageView;
    public ViewXYHolder(View view){
        imageView = view;
    }

//看到这个是不是感觉跟第一种方法一样的感脚,只是封装的不同
public void setXY(XYHolder xyHolder) {
    imageView.setX(xyHolder.getX());
    imageView.setY(xyHolder.getY());
}

public XYHolder getXY() {
    return new XYHolder(imageView.getX(), imageView.getY());
}
}


 
 
而其实,对于这个例子,使用的对象是一个View,Android系统中有封装View属性动画的一个类: ViewPropertyAnimator,其简单使用方式如下:
 
 
private void startViewPropertyAnimation(){
    ViewPropertyAnimator viewPropertyAnimator;
    viewPropertyAnimator = mImageView.animate().x(500).y(500);
    viewPropertyAnimator.setDuration(3000);
    viewPropertyAnimator.start();
}

同样也能实现上面的动画效果,只是只局限于View,不管方法怎么变,但是最终原理都是一样的,都是要同时改变X 和 Y两个属性的值。
复杂一点的例子还是直接参考ApiDemo比较好,ApiDemo里面有个Custom Evaluator,值得学习!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值