Android 属性动画 - TypeEvaluator

本文介绍了如何在Android属性动画中自定义TypeEvaluator,用于实现更复杂的动画效果。讲解了TypeEvaluator接口的工作原理,以及如何配合ValueAnimator和AnimatorUpdateListener来控制动画属性的变化,以实现如背景变色、控件移动和缩放等效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android动画系列:

这里写图片描述
对于Evaluators,即属性动画计算器,官方根据实际需求已经为我们实现了几种,但在实际开发过程中,官方定义的那几种并不能满足我们实际的需求,比如在背景变色的同时将控件移动并缩小,有的人说可以使用AnimatorSet实现,当然能AnimatorSet可以轻易实现,假如我们就用一个ValueAnimator该怎么实现呢?

之前有提到过TypeEvaluator这个接口,其用来实现自定义动画属性值的计算器。TypeEvaluator接口中只定义了一个方法,evaluate(float fraction, T startValue, T endValue),evaluate可以接受三个参数fraction,startValue,endValue,其中startValue和endValue都是使用泛型定义的,意味着我们可以自定义传入的计算的动画属性,其返回值也使我们定义的的动画属性类型,以达到在AnimatorUpdateListener监听中,计算出来的属性值都是我们定义的。

TypeEvaluator的实现类一般与 setEvaluator(TypeEvaluator)方法或者ofObject(TypeEvaluator, Object… values)配合使用,来定义动画的属性值计算器。

  • fraction : 动画进度
  • startValue T : 动画属性初始值
  • endValue T: 动画属性结束值

自定义TypeEvaluator

首先,定一个动画相关属性的类MyPoint,其内包含了trance、color、scale等三个动画相关的属性。

public class MyPoint {
    float trance; // 移动距离
    int color; // 颜色
    float scale; // 缩放比例

    ****
}

接下来,我们自定义一个Evaluator类,命名为MyEvaluator,其实现了接口TypeEvaluator,并将刚才定义的MyPoint作为动画的属性值类型。在evaluate()方法中,根据动画的执行进度,对trance、color、scale等三个属性分别做了相应处理。

public class MyEvaluator implements TypeEvaluator<MyPoint> {
    @Override
    public MyPoint evaluate(float fraction, MyPoint pointStart, MyPoint pointEnd) {
        MyPoint pointCurrent = new MyPoint();

        pointCurrent.setColor(getCurrentColor(fraction, pointStart.getColor(), pointEnd.getColor()));
        pointCurrent.setTrance(getCurrentTrance(fraction, pointStart.getTrance(), pointEnd.getTrance()));
        pointCurrent.setScale(getCurrentScale(fraction, pointStart.getScale(), pointEnd.getScale()));
        return pointCurrent;
    }

    /**
     * 根据fraction值来计算当前的颜色。
     */
    private int getCurrentColor(float fraction, int startColor, int endColor) {
        int redCurrent;
        int blueCurrent;
        int greenCurrent;
        int alphaCurrent;

        int redStart = Color.red(startColor);
        int blueStart = Color.blue(startColor);
        int greenStart = Color.green(startColor);
        int alphaStart = Color.alpha(startColor);

        int redEnd = Color.red(endColor);
        int blueEnd = Color.blue(endColor);
        int greenEnd = Color.green(endColor);
        int alphaEnd = Color.alpha(endColor);

        int redDifference = redEnd - redStart;
        int blueDifference = blueEnd - blueStart;
        int greenDifference = greenEnd - greenStart;
        int alphaDifference = alphaEnd - alphaStart;

        redCurrent = (int) (redStart + fraction * redDifference);
        blueCurrent = (int) (blueStart + fraction * blueDifference);
        greenCurrent = (int) (greenStart + fraction * greenDifference);
        alphaCurrent = (int) (alphaStart + fraction * alphaDifference);

        return Color.argb(alphaCurrent, redCurrent, greenCurrent, blueCurrent);
    }

    /**
     * 根据fraction值来计算当前的移动距离
     */
    private float getCurrentTrance(float fraction, float tranceStart, float tranceEnd) {
        float tranceCurrent;
        float difference;

        difference = tranceEnd - tranceStart;

        tranceCurrent = tranceStart + difference * fraction;

        return tranceCurrent;
    }

    /**
     * 根据fraction值来计算当前缩放比例
     */
    private float getCurrentScale(float fraction, float scaleStart, float scaleEnd) {
        float scaleCurrent;
        float difference;

        difference = scaleEnd - scaleStart;

        scaleCurrent = scaleStart + difference * fraction;

        return scaleCurrent;
    }
}

最后使用静态方法ofObject(TypeEvaluator, T…values)创建ValueAnimator对象valueAnimator,通过系列setXX()方法,对valueAnimator做动画的相应设置,在AnimatorUpdateListener监听的onAnimationUpdate(ValueAnimator)方法中,通过getAnimatedValue()可以获得当前的动画的属性值,其类型强转为MyPoint,再设定View的相关属性,以达到动画效果。

//起始颜色为红色
int startColor = 0xffff0000;
//终止颜色为绿色
int endColor = 0xff00ff00;

MyPoint pointStart = new MyPoint(0f, startColor, 1.0f);
MyPoint pointEnd = new MyPoint(400f, endColor, 0.2f);

// 通过静态方法构建一个ValueAnimator对象
// 动画属性值计算器使用自定义的计算器(MyEvaluator)
ValueAnimator valueAnimator = ValueAnimator.ofObject(new MyEvaluator(), pointStart, pointEnd);
// 设置作用对象
valueAnimator.setTarget(btnProperty);
// 设置动画无限循环
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
// 设置动画执行时间
valueAnimator.setDuration(4000);
// 添加动画更新监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        // 获取当前值
        MyPoint mValue = (MyPoint) animation.getAnimatedValue();
        // 动画进度(t/duration)
        float fraction = animation.getAnimatedFraction();

        Log.d("PropertyActivity", "mValue:" + mValue.toString());
        Log.d("PropertyActivity", "fraction:" + fraction + " | t:" + fraction * animation.getDuration());

        // 设置横向偏移量
        btnProperty.setTranslationX(mValue.getTrance() * 0.5f);
        // 设置纵向偏移量
        btnProperty.setTranslationY(mValue.getTrance());
        // 设置背景颜色
        btnProperty.setBackgroundColor(mValue.getColor());
        // 设置横向缩放
        btnProperty.setScaleX(mValue.getScale());
        // 设置纵向缩放
        btnProperty.setScaleX(mValue.getScale());
    }
});

valueAnimator.start();

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值