樓主前段時間做一個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中做開始動畫,然后畫出具體的圖形,則大功告成。