1.简述
自定义view绘制动画原理就是,定义一个value值,值随着动画进度改变而改变;在onDraw()中,绘制时使其中某个或多个参数值*value/100(假设设置动画进度最大值100);而后设置动画对象时,value每次变化时,调用postInvalidate()通知视图重绘,从而再次调用onDraw()…如此循环,从而实现绘制动画。
2.使用
实际使用效果:
2.1代码解释
2.1.1 动画控制
private int animProgress = 0;//定义一个 跟随动画进度变化的value值
private ValueAnimator mAnimtor ;
public void startAnim(){
if (mAnimtor == null){
mAnimtor = ValueAnimator.ofInt(0,100);
mAnimtor.setDuration(800);//动画持续时长
mAnimtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
animProgress = (int) valueAnimator.getAnimatedValue();
postInvalidate();
}
});
}
mAnimtor.start();
}
2.1.2初始化绘制
private Paint mPaint;
private Path mPath;
public DiyViewAnim(Context context) {
super(context);
mPaint = new Paint();
mPath = new Path();
}
public DiyViewAnim(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPath = new Path();
}
2.1.3根据value值动态绘制
其中条形图绘制数值意义可参考自定义view(4):自绘式
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.reset();
mPath.reset();
//1.画坐标轴
mPaint.setColor(Color.parseColor("#404040"));
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(120, 120);//y轴顶点(120,120)
mPath.rLineTo(0, 600);//y轴方向
mPath.rLineTo(800, 0);//x轴方向
canvas.drawPath(mPath, mPaint);//绘制
//2.画x轴label
mPaint.reset();
mPaint.setColor(Color.parseColor("#404040"));
mPaint.setTextSize(18);//px
mPaint.setStyle(Paint.Style.FILL);
//假数据
canvas.drawText("1月", 120 + 20, 120 + 600 + 28, mPaint);
canvas.drawText("2月", 120 + 20 * 2 + 60 * (2 - 1), 600 + 120 + 28, mPaint);
canvas.drawText("3月", 120 + 20 * 3 + 60 * (3 - 1), 600 + 120 + 28, mPaint);
//3.画条形图
float[] lines = {
120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
600 + 120,
120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
600 + 120 - 180*animProgress/100,
120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
600 + 120,
120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
600 + 120 - 420*animProgress/100,
120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
600 + 120,
120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
600 + 120 - 140*animProgress/100
};
mPaint.reset();
mPaint.setColor(Color.parseColor("#6ce4d8"));
mPaint.setStrokeWidth(60);
canvas.drawLines(lines, mPaint);
}
2.2 xml使用
<com.cupster.base_super_resource.DiyViewAnim
android:id="@+id/diy_chart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
DiyViewAnim diyChart = findViewById(R.id.diy_chart);
diyChart.startAnim();
3.完整View代码
package com.cupster.base_super_resource;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
public class DiyViewAnim extends View {
public DiyViewAnim(Context context) {
super(context);
mPaint = new Paint();
mPath = new Path();
}
public DiyViewAnim(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPath = new Path();
}
public DiyViewAnim(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPath = new Path();
}
public DiyViewAnim(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mPaint = new Paint();
mPath = new Path();
}
private Paint mPaint;
private Path mPath;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.reset();
mPath.reset();
//1.画坐标轴
mPaint.setColor(Color.parseColor("#404040"));
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(120, 120);//y轴顶点(120,120)
mPath.rLineTo(0, 600);//y轴方向
mPath.rLineTo(800, 0);//x轴方向
canvas.drawPath(mPath, mPaint);//绘制
//2.画x轴label
mPaint.reset();
mPaint.setColor(Color.parseColor("#404040"));
mPaint.setTextSize(18);//px
mPaint.setStyle(Paint.Style.FILL);
//假数据
canvas.drawText("1月", 120 + 20, 120 + 600 + 28, mPaint);
canvas.drawText("2月", 120 + 20 * 2 + 60 * (2 - 1), 600 + 120 + 28, mPaint);
canvas.drawText("3月", 120 + 20 * 3 + 60 * (3 - 1), 600 + 120 + 28, mPaint);
//3.画条形图
float[] lines = {
120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
600 + 120,
120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
600 + 120 - 180*animProgress/100,
120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
600 + 120,
120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
600 + 120 - 420*animProgress/100,
120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
600 + 120,
120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
600 + 120 - 140*animProgress/100
};
mPaint.reset();
mPaint.setColor(Color.parseColor("#6ce4d8"));
mPaint.setStrokeWidth(60);
canvas.drawLines(lines, mPaint);
}
private int animProgress = 0;
private ValueAnimator mAnimtor ;
public void startAnim(){
if (mAnimtor == null){
mAnimtor = ValueAnimator.ofInt(0,100);
mAnimtor.setDuration(800);
mAnimtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
animProgress = (int) valueAnimator.getAnimatedValue();
postInvalidate();
}
});
}
mAnimtor.start();
}
}