You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Animator与ObjectAnimator咨询:新手求动画实现方案

Android动画进阶实现思路

你说的没错,Android Studio确实没有内置的Animation可视化编辑视图。除了你已经尝试的XML属性动画集合(代码已翻译注释如下),这里分享几个相对小众但实用的实现思路:

<set
    android:ordering=["同时执行" | "顺序执行"]>

    <objectAnimator
        android:propertyName="属性名"
        android:duration="时长(毫秒)"
        android:valueFrom="起始值(浮点数 | 整数 | 颜色)"
        android:valueTo="目标值(浮点数 | 整数 | 颜色)"
        android:startOffset="延迟时长(毫秒)"
        android:repeatCount="重复次数"
        android:repeatMode=["重启" | "反向播放"]
        android:valueType=["整数类型" | "浮点类型"]/>

    <animator
        android:duration="时长(毫秒)"
        android:valueFrom="起始值(浮点数 | 整数 | 颜色)"
        android:valueTo="目标值(浮点数 | 整数 | 颜色)"
        android:startOffset="延迟时长(毫秒)"
        android:repeatCount="重复次数"
        android:repeatMode=["重启" | "反向播放"]
        android:valueType=["整数类型" | "浮点类型"]/>

    <set>
        ...
    </set>
</set>

1. 利用Paint的Shader实现自定义渐变动画

很多属性动画只能修改View的固有属性,而通过Paint的Shader可以实现更复杂的渐变流动效果,比如按钮扫光、文字渐变填充。核心思路是在自定义View的onDraw方法中,动态更新Shader的位置或参数,再通过invalidate()触发重绘:

public class ShaderAnimView extends View {
    private Paint mPaint;
    private LinearGradient mGradient;
    private Matrix mMatrix;
    private int mTranslateX;

    public ShaderAnimView(Context context) {
        super(context);
        init();
    }

    private void init() {
        mPaint = new Paint();
        // 创建左右渐变的Shader,颜色从透明到白色再到透明
        mGradient = new LinearGradient(-getWidth(), 0, 0, 0,
                new int[]{Color.TRANSPARENT, Color.WHITE, Color.TRANSPARENT},
                new float[]{0f, 0.5f, 1f}, Shader.TileMode.CLAMP);
        mPaint.setShader(mGradient);
        mMatrix = new Matrix();

        // 启动动画
        ValueAnimator animator = ValueAnimator.ofInt(0, getWidth());
        animator.setDuration(1500);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.addUpdateListener(animation -> {
            mTranslateX = (int) animation.getAnimatedValue();
            invalidate();
        });
        animator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 更新Shader的位置
        mMatrix.setTranslate(mTranslateX, 0);
        mGradient.setLocalMatrix(mMatrix);
        // 绘制文字或图形
        canvas.drawText("扫光动画", 50, 100, mPaint);
    }
}

2. 用PathMeasure实现路径跟随动画

如果需要让View沿着自定义曲线移动(比如圆形、波浪形轨迹),PathMeasure可以精准获取路径上任意位置的坐标和切线方向,结合ValueAnimator就能实现轨迹动画,还能同步控制View的旋转方向:

// 先创建路径,比如一个圆形
Path path = new Path();
path.addCircle(300, 300, 200, Path.Direction.CW);

PathMeasure measure = new PathMeasure(path, false);
float pathLength = measure.getLength();

ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(animation -> {
    float value = (float) animation.getAnimatedValue();
    float[] pos = new float[2];
    float[] tan = new float[2];
    // 获取当前进度对应的路径点坐标和切线方向
    measure.getPosTan(pathLength * value, pos, tan);
    // 设置View的位置(居中对齐路径点)
    view.setTranslationX(pos[0] - view.getWidth()/2);
    view.setTranslationY(pos[1] - view.getHeight()/2);
    // 计算旋转角度,让View始终沿着路径切线方向
    float angle = (float) (Math.atan2(tan[1], tan[0]) * 180 / Math.PI);
    view.setRotation(angle);
});
animator.start();

3. 借助TransitionDrawable实现图层切换动画

这个组件可以快速实现两个Drawable之间的淡入淡出切换,不需要复杂的属性动画配置,适合按钮状态切换、图片渐变替换等场景:

// 准备两个要切换的Drawable
Drawable drawable1 = getResources().getDrawable(R.drawable.ic_state_normal);
Drawable drawable2 = getResources().getDrawable(R.drawable.ic_state_selected);

TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{drawable1, drawable2});
button.setBackground(transitionDrawable);

// 启动切换动画,时长500毫秒
transitionDrawable.startTransition(500);
// 如果需要反向切换,调用reverseTransition(500)

4. 自定义TypeEvaluator实现非线性动画

系统默认的动画多是线性或简单插值,自定义TypeEvaluator可以实现弹性、弹跳等物理效果,比如模拟弹簧回弹:

// 自定义弹性Evaluator
class SpringEvaluator implements TypeEvaluator<Float> {
    // 弹性系数,值越大弹性越强
    private float mStiffness = 0.2f;
    // 阻尼系数,值越大衰减越快
    private float mDamping = 0.8f;

    @Override
    public Float evaluate(float fraction, Float startValue, Float endValue) {
        float diff = endValue - startValue;
        // 用简谐运动公式计算当前值
        float value = (float) (diff * (1 - Math.exp(-fraction / mStiffness) * Math.cos(fraction * Math.PI / mDamping)));
        return startValue + value;
    }
}

// 使用这个Evaluator创建动画
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", 0, 300);
animator.setEvaluator(new SpringEvaluator());
animator.setDuration(1500);
animator.start();

内容的提问来源于stack exchange,提问作者Shubham Sevak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:02:33