属性动画之 ObjectAnimator

上一篇文章中,我们利用 ValueAnimator 配合 View 的一些方法实现了动画效果,在实现的过程我们需要给 Animator 设置一个监听器去监听数值的变化,Android 还提供了一个 ObjectAnimator 直接将 ValueAnimtor 的计算过程直接应用到指定的组件上。

ObjectAnimator 是 ValueAnimator 的子类,并且把时序引擎和 ValueAnimator 对象的计算值组合到一起,让目标对象的命名属性具备动画能力。这样使得让任意对象具有动画效果变的更加容易,如不在需要实现 ValueAnimator.AnimatorUpdateListener 接口,因为被动画的属性会自动的更新。

实例化一个 ObjectAnimator 对象与实例化一个 ValueAnimator 对象类似,但是,它还需要跟动画期间的参数一起,指定动画对象和对象动画属性(用一个字符串)的名字:

ImageView img = findViewById(R.id.img);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(img, "alpha", 0, 1, 0, 1); 

在上面的例子中:
我们通过调用 ObjectAnimator 类的 ofFloat 方法来创建一个 ObjectAnimator 对象,ofFloat 接收的参数需要说明:

  • img:接收动画的组件
  • alpha:动画属性
  • 可变长参数:和 ValueAnimator 当中的可变参数一样,代表数值的过渡范围

Android 给我们提供了以下动画属性:

  • alpha:透明度

  • rotation:围绕圆心旋转

  • rotationX:围绕 X 轴旋转

  • rotationY:围绕 Y 轴旋转

  • translationX:X轴方向位移

  • translationY:Y轴方向位移

  • scaleX:X轴方向缩放

  • scaleY:Y轴方向缩放

一个例子:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button alpha, rotate, translate, scale;
    private ImageView img;

    private ObjectAnimator objectAnimator;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        alpha = (Button) findViewById(R.id.alpha);
        rotate = (Button) findViewById(R.id.rotate);
        translate = (Button) findViewById(R.id.translate);
        scale = (Button) findViewById(R.id.scale);
        img = (ImageView) findViewById(R.id.img);

        alpha.setOnClickListener(this);
        rotate.setOnClickListener(this);
        translate.setOnClickListener(this);
        scale.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.alpha:
                imageAlpha();
                break;
            case R.id.rotate:
                imageRotate();
                break;
            case R.id.translate:
                imageTranslate();
                break;
            case R.id.scale:
                imageScale();
                break;

        }
    }

    private void imageScale() {
        objectAnimator = ObjectAnimator.ofFloat(img, "scaleY", 2f, 4f, 1f, 0.5f, 1f);
        objectAnimator.setDuration(3000);
        objectAnimator.start();
    }

    private void imageTranslate() {
        objectAnimator = ObjectAnimator.ofFloat(img, "translationX", 320);
        objectAnimator.setDuration(3000);
        objectAnimator.start();
    }

    private void imageRotate() {
        objectAnimator = ObjectAnimator.ofFloat(img, "rotation", 0, 360);
        objectAnimator.setDuration(3000);
        objectAnimator.setRepeatCount(-1);
        objectAnimator.start();
    }

    private void imageAlpha() {
        objectAnimator = ObjectAnimator.ofFloat(img, "alpha", 1, 0, 1);
        objectAnimator.setDuration(3000);
        objectAnimator.setRepeatCount(-1);
        objectAnimator.start();
    }
}

ObjectAnimator 的工作过程

我们在获取 ObjectAnimator 对象需要指定动画类型,动画执行之后,系统会根据我们的可变长参数计算出动画值,并且再调用我们的 目标组件set属性值 方法,在上面的例子渐变动画中,系统会自动调取 ImageView 对象的 setAlpha 方法,并且将其计算的值设置进去。

所以,当我们实现一个自定义 View 的时候,就可以创建一个 setXXX 方法,然后再在动画中设置动画类型为 xxx,这样我们就可以动态的改变该 View 的属性,从而实现动画效果了。

网上的一个例子:

public class Ponit {
    private int mRadius;

    public Ponit() {
    }

    public Ponit(int mRadius) {
        this.mRadius = mRadius;
    }

    public int getRadius() {
        return mRadius;
    }

    public void setRadius(int mRadius) {
        this.mRadius = mRadius;
    }
}
public class CircleView extends View {
    private Ponit mCurrentPoint = new Ponit();
    private Paint mPiant ;
    private int mScreenWidth;//屏幕宽度
    public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPiant = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPiant.setColor(Color.RED);
        mPiant.setStyle(Paint.Style.FILL);
        mScreenWidth = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mCurrentPoint != null){
            canvas.drawCircle(mScreenWidth/2,getY()+getPaddingTop(),mCurrentPoint.getRadius(),mPiant);
        }
    }
    public int getPointRadius(){  //这个get方法只作为默认值出现在这里的
        return 50;
    }
    public void setPointRadius(int radius){//这里set方法必须和ObjectAnimator中的属性值对应
        mCurrentPoint.setRadius(radius);
        invalidate();
    }
}

这个动画效果就是圆的大小会逐渐改变的动画~

Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1