最近,项目里需要加入3d柱状图展示数据,在网上找了找,发现和需求有点出入(可能自己没找对),于是就自己画了个,随便锻炼下自己,下面就把这个demo写出来。
public class CustomBar extends View {
private Context mContext;
private Paint customPaint,customDrawPain, textPaint, linePaint;
private int width, height, lineCount = 7;
private double all;
private int yTextTemp;//每格数值
private int yTextIndex = 0;
private int lineTemp;//每格高度
private int lineIndex = height;
private int xSpacing;
private float index, valuesIndex;
private int xWidth;
public CustomBar(Context context) {
this(context,null);
}
public CustomBar(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mContext = context;
initCustomPain();
initTextPain();
}
private void initTextPain() {
textPaint = new Paint();//y轴值画笔
textPaint.setStrokeWidth(2);
textPaint.setColor(Color.parseColor("#E6E6E6"));
textPaint.setTextSize(20f);
linePaint = new Paint();//坐标y轴横线的画笔
linePaint.setStrokeWidth(2);
linePaint.setColor(Color.BLACK);
linePaint.setTextSize(20f);
}
private void initCustomPain() {
customPaint = new Paint();//画笔
customPaint.setColor(Color.parseColor("#F08F3E"));
customPaint.setStyle(Paint.Style.FILL);
customPaint.setTextSize(getResources().getDimension(R.dimen.text_size_h_xxx));
customDrawPain = new Paint();//3d阴影背景画笔
customDrawPain.setColor(Color.parseColor("#F8D6C2"));
customDrawPain.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = 300;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = 300;
}
setMeasuredDimension(width, height);
height = height - Utils.dip2px(mContext, 25);//计算出去边距的高度
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
yTextTemp = (int) Math.ceil(all / 5.0);//y轴每格数值
yTextIndex = 0;//y轴起始值
lineTemp = height / 7;//y轴每格高度
lineIndex = height;//y==0的高度
index = textPaint.measureText("100");
xWidth = (int) ((width - index) / 9);//柱状图宽度
xSpacing = (int) ((width - index - xWidth * 2) / 3);
for (int i = 0; i < lineCount; i++) {//画出坐标
canvas.drawText((int) yTextIndex + "", 0, lineIndex, linePaint);//绘出刻度值
canvas.drawLine(index, lineIndex, width, lineIndex, textPaint);//绘出y轴
lineIndex -= lineTemp;
yTextIndex += yTextTemp;
}
if (valuesIndex <= 10) {//绘制柱状
drawCustom(canvas, xSpacing, xWidth, valuesIndex, Utils.dip2px(mContext, 4), Utils.dip2px(mContext, 5));
} else {
drawCustom(canvas, xSpacing, xWidth, 10, Utils.dip2px(mContext, 4), Utils.dip2px(mContext, 5));
}
}
/**
* 画柱状
*
* @param canvas
* @param left x坐标
* @param width 宽度
* @param value 值
* @param drawPadding 背景左侧间距
* @param topPadding 背景top边距
*/
private void drawCustom(Canvas canvas, int left, int width, float value, float drawPadding, float topPadding) {
if (value > 0) {
canvas.drawRect(left, height - value / yTextTemp * lineTemp - topPadding, left + width, height, customDrawPain);
canvas.drawRect(left + drawPadding, height - value / yTextTemp * lineTemp, left + width + drawPadding, height, customPaint);
canvas.drawLine(left, height - value / yTextTemp * lineTemp - topPadding, left + drawPadding, height - value / yTextTemp * lineTemp, customPaint);
Path path = new Path();
path.moveTo(left + width, height - value / yTextTemp * lineTemp - topPadding);// 此点为多边形的起点
path.lineTo(left + width + drawPadding, height - value / yTextTemp * lineTemp);
path.lineTo(left + width, height - value / yTextTemp * lineTemp);
path.close(); // 使这些点构成封闭的多边形
canvas.drawPath(path, customDrawPain);
canvas.drawText(StringUtils.prasePercentage(value / 100), left + width / 3, height - value / yTextTemp * lineTemp - topPadding - Utils.dip2px(mContext, 4), customPaint);
}
canvas.drawText("title", left, height + Utils.dip2px(mContext, 20), customPaint);
}
public void setDates(float vipValus) {
this.all = vipValus;
startAnimationForEvery(0, (float) all, 1200);
}
public class LineEvaluator implements TypeEvaluator {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startPoint = (float) startValue;
float endPoint = (float) endValue;
float y = (startPoint + fraction * (endPoint - startPoint));
return y;
}
}
private void startAnimationForEvery(float startPoint, float endPoint, long duration) {
final ValueAnimator anim = ValueAnimator.ofObject(new LineEvaluator(), startPoint, endPoint);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
valuesIndex = (float) animation.getAnimatedValue();
invalidate();
}
});
anim.addListener(new CustomAnimator() {
@Override
public void onAnimationEnd(Animator animation) {
anim.cancel();
}
});
anim.setDuration(duration);
anim.start();
}
}