Android颜色渐变动画效果的实现

举报
计蒙不吃鱼 发表于 2025/06/09 01:03:12 2025/06/09
【摘要】 本文介绍了在Android中实现颜色渐变动画效果的方法,重点讲解了插值器(TypeEvaluator)的使用与自定义。通过Android自带的颜色插值器ArgbEvaluator,可以轻松实现背景色的渐变动画。文章详细分析了ArgbEvaluator的核心代码,并演示了如何利用Color.colorToHSV和Color.HSVToColor方法自定义颜色插值器MyColorEvaluator。

系列文章目录

Android颜色渐变动画效果的实现

文章最后有源码

前言

案例效果的实现比较简单,利用Android自带的颜色插值器ArgbEvaluator()进行计算即可,而本文的重点就是讲讲插值器。

效果图:

一、Android中插值器TypeEvaluator。

TypeEvaluator是一个接口,在开发中可以自定义该接口实例,利用ValueAnimator的setEvaluator(TypeEvaluator)方法来控制动画的更新计算表达式。在日常开发中,不可能只是需要操纵单一数值的变化,如果需要同时操纵对象的多个属性,如定义动画的x,y移动的坐标等,那就需要对TypeEvaluator有所了解了。

二、案例效果实现

1.利用Android自带的颜色插值器ArgbEvaluator

  ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
        colorAnim.setDuration(4000);
        colorAnim.setEvaluator(new ArgbEvaluator());
        colorAnim.setRepeatCount(ValueAnimator.INFINITE);
        colorAnim.setRepeatMode(ValueAnimator.REVERSE);
        colorAnim.start();

2.看看Android自带颜色插值器ArgbEvaluator核心代码

    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        float startA = ((startInt >> 24) & 0xff) / 255.0f;
        float startR = ((startInt >> 16) & 0xff) / 255.0f;
        float startG = ((startInt >>  8) & 0xff) / 255.0f;
        float startB = ( startInt        & 0xff) / 255.0f;

        int endInt = (Integer) endValue;
        float endA = ((endInt >> 24) & 0xff) / 255.0f;
        float endR = ((endInt >> 16) & 0xff) / 255.0f;
        float endG = ((endInt >>  8) & 0xff) / 255.0f;
        float endB = ( endInt        & 0xff) / 255.0f;

        // 将sRGB转化成线性
        startR = (float) Math.pow(startR, 2.2);
        startG = (float) Math.pow(startG, 2.2);
        startB = (float) Math.pow(startB, 2.2);

        endR = (float) Math.pow(endR, 2.2);
        endG = (float) Math.pow(endG, 2.2);
        endB = (float) Math.pow(endB, 2.2);

        //在线性空间中计算插值的颜色
        float a = startA + fraction * (endA - startA);
        float r = startR + fraction * (endR - startR);
        float g = startG + fraction * (endG - startG);
        float b = startB + fraction * (endB - startB);

        //转换回sRGB在[0..255]范围
        a = a * 255.0f;
        r = (float) Math.pow(r, 1.0 / 2.2) * 255.0f;
        g = (float) Math.pow(g, 1.0 / 2.2) * 255.0f;
        b = (float) Math.pow(b, 1.0 / 2.2) * 255.0f;

        return Math.round(a) << 24 | Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b);
    }

3.根据ArgbEvaluator的实现来自定义一个颜色插值器

public class MyColorEvaluator implements TypeEvaluator

接下来换一种颜色的计算方式,在本人看相关api的过程中,发现Color中有colorToHSV和HSVToColor的方法,于是在网上找了一个HVS的计算方式。(以下代码来源于网络)。

 @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        Color.colorToHSV(startValue,startHsv);
        Color.colorToHSV(endValue,endHsv);
        int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);
        // 计算当前动画完成度(fraction)所对应的颜色值
        if (endHsv[0] - startHsv[0] > 180) {
            endHsv[0] -= 360;
        } else if (endHsv[0] - startHsv[0] < -180) {
            endHsv[0] += 360;
        }
        outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;
        if (outHsv[0] > 360) {
            outHsv[0] -= 360;
        } else if (outHsv[0] < 0) {
            outHsv[0] += 360;
        }
        outHsv[1]=startHsv[1]+(endHsv[1]-startHsv[1])*fraction;
        outHsv[2]=startHsv[2]+(endHsv[2]-startHsv[2])*fraction;
        return Color.HSVToColor(alpha,outHsv);

    }

4.使用自己定义的颜色插值器MyColorEvaluator

 ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
        colorAnim.setDuration(4000);
        colorAnim.setEvaluator(new MyColorEvaluator());
        colorAnim.setRepeatCount(ValueAnimator.INFINITE);
        colorAnim.setRepeatMode(ValueAnimator.REVERSE);
        colorAnim.start();

三、源码

ColorGradient.java:

public class ColorGradient extends View {

    public ColorGradient(Context context) {
        super(context);
    }

    public ColorGradient(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        animation();
    }

    public ColorGradient(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    private void animation(){
        ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
        colorAnim.setDuration(4000);
        colorAnim.setEvaluator(new MyColorEvaluator());
        colorAnim.setRepeatCount(ValueAnimator.INFINITE);
        colorAnim.setRepeatMode(ValueAnimator.REVERSE);
        colorAnim.start();
    }
}

MyColorEvaluator.java:

public class MyColorEvaluator implements TypeEvaluator<Integer> {
    float[] startHsv=new float[3];
    float[] endHsv=new float[3];
    float[] outHsv=new float[3];

    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        Color.colorToHSV(startValue,startHsv);
        Color.colorToHSV(endValue,endHsv);
        int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);
        // 计算当前动画完成度(fraction)所对应的颜色值
        if (endHsv[0] - startHsv[0] > 180) {
            endHsv[0] -= 360;
        } else if (endHsv[0] - startHsv[0] < -180) {
            endHsv[0] += 360;
        }
        outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;
        if (outHsv[0] > 360) {
            outHsv[0] -= 360;
        } else if (outHsv[0] < 0) {
            outHsv[0] += 360;
        }
        outHsv[1]=startHsv[1]+(endHsv[1]-startHsv[1])*fraction;
        outHsv[2]=startHsv[2]+(endHsv[2]-startHsv[2])*fraction;
        return Color.HSVToColor(alpha,outHsv);

    }
}

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。