上一篇文章中,我们利用 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 接收的参数需要说明:
Android 给我们提供了以下动画属性:
一个例子:
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 对象需要指定动画类型,动画执行之后,系统会根据我们的可变长参数计算出动画值,并且再调用我们的 目标组件
的 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();
}
}
这个动画效果就是圆的大小会逐渐改变的动画~