楼主前段时间做一个android项目,其中一个需求是需要制作一个动画,但是之前楼主没接触过android动画,所以在网上搜了下,并且也有人推荐可以试下用属性动画,所以我就百度了下属性动画怎么用,并顺便写下valueAnimator的用法。
其实valueAnimator用起来非常非常简单:
首先先讲下核心函数:
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(Math.min(((getRight()-getLeft()))/2,(getBottom()-getTop())/2)), startPoint, endPoint); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint = (Point) animation.getAnimatedValue(); invalidate(); } }); anim.setRepeatMode(ValueAnimator.RESTART); anim.setRepeatCount(1000); anim.start();
首先对这几行代码进行一个简单的解释,第一行为初始化一个valueAnimator类,然后其中第一个参数是一个事先定以后好的类,这个在后边具体解释,,然后第二个第三个参数分别代表起始位置和结束位置,当然这个也可以不写,通过其他方式也可传入进去,这个也放在后边解释。
第二行代码,是用来添加监听器,这个监听器作用则是实时的获取当前坐标,赋值给currentPoint(这个对象是自己声明的,这个对象可以在全局中声明和使用)。
然后invalidate()则是更新当前图形坐标。
setRepeatMode(),则是选择动画执行的模式,有两种模式,即ValueAnimator.RESTART(重复),ValueAnimator.REVERSE(反方向重复)
anim.setRepeatCount(1000)设置重复次数。
anim.setDuration(40000);设置每次执行时间。
那这个说完了,则把刚才的遗留问题解决了,下边贴出那个类的代码
public class PointEvaluator implements TypeEvaluator { float r; public PointEvaluator(float r) { this.r = r; } @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Point startPoint = (Point) startValue; Point endPoint = (Point) endValue; float x = new Float(startPoint.getX() - Math.sin(fraction* Math.PI*2*20)*r); float y = new Float(startPoint.getY() - (r - Math.cos(fraction* Math.PI*2*20) * r) ); Point point = new Point(x, y); return point; } }
这个类中,最重要的是evaluate函数,这个函数的作用是计算动画的过程,其中fraction参数的值是从0-1,然后动画执行一次,fraction从0到1执行一次。因此,在这个函数中,通过fraction函数来计算当前的坐标,因此要利用好这个fraction参数。这里的两个参数startValue和endValue则是刚才上述讲的传入的两个参数,为什么说可传可不传,是因为你也可以通过对这个类添加构造函数,然后传进来初始和结束值。
然后这个类怎么用呢?
看下方代码:
public class MyAnimView extends View { public static final float RADIUS = 10f; private Point currentPoint; private Paint mPaint; public MyAnimView(Context context, AttributeSet attrs) { super(context, attrs); Log.e("view","-------------构造函数"); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(5l); } @Override protected void onDraw(Canvas canvas) { if (currentPoint == null) { currentPoint = new Point(RADIUS, RADIUS); drawCircle(canvas); startAnimation(); } else { drawCircle(canvas); } } private void drawCircle(Canvas canvas) { float x = currentPoint.getX(); float y = currentPoint.getY(); canvas.drawLine((getLeft()+getRight())/2, (getBottom()+getTop())/2,x,y,mPaint); } public void startAnimation() { Point startPoint = new Point((getLeft()+getRight())/2, (getBottom()+getTop())/2+ Math.min(((getRight()-getLeft()))/2,(getBottom()-getTop())/2)); Point endPoint = startPoint; Log.e("myAnim","x="+(getLeft()+getRight())/2+" y="+(getTop()+getBottom())/2); Log.e("myAnim","left="+getLeft()+" right="+getRight()+" top="+getTop()+" botton"+getBottom()); ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(Math.min(((getRight()-getLeft()))/2,(getBottom()-getTop())/2)), startPoint, endPoint); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint = (Point) animation.getAnimatedValue(); invalidate(); } }); anim.setRepeatMode(ValueAnimator.RESTART); anim.setRepeatCount(1000); anim.setDuration(4000); anim.start(); } }
通过自定义view,然后在其中ondraw中做开始动画,然后画出具体的图形,则大功告成。