自定义一个动态饼状图

效果图:
生成过程是动态的

下面是主要的view代码。他的自定义属性可以设可以不设,可以通过在activity里获取到的view实例
设置颜色和值。颜色和值需字符串形式。你也可以自己修改。
还有AngelEvaluator类
public class AngelEvaluator implements TypeEvaluator {
@Override
public Object evaluate(float fraction, Object startValue, Object Value) {
int startAngel = (int)startValue;
int Angel = (int)Value;
int value = (int) (startAngel + (Angel) *fraction);
return value;
}
}
这个类可以自己写控制动画过程 要改变这种慢-快-慢的速度可以改动画的Interpolator

package com.resourse.skintest;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Switch;

import java.math.BigDecimal;

/**
* Created by yang on 2016/9/20 0020.
* 画图的思路就是用属性动画使curAngel从0到360度增加。
* 然后在每次增加的时候调用invalidate使他执行ondraw。在ondraw里面就画出扇形
* 画扇形的时候又根据不同的角度,画不同的颜色。进行区分
* 画完图之后,就是curAngel等于360度之后。就开始画线条,线条要重复画count次。
*
*/
public class MyPieChart extends View {

/**
* 份数
*/
int pieCount;
/**
* 颜色和值的字符串形式
*/
String pieValue;
/**
* 依次的颜色值
*/
String pieColor = “#ff0000,#ffcc00,#00cc00,#ff6600,#3366cc,#cc0000,#00ff00,#00ccff,#0fdd0f,#dddddd,#90fd00”;

/**
* 颜色和值的字符串数组形式
*/
String[] color, value;

float tValue;
/**
* 画笔
*/
Paint mPaint;
RectF oval = new RectF(250, 250, 550, 550);
/**
* 半径
*/
int R = 150;
/**
* 圆心
*/
int[] Radius = {400, 400};
Rect mBound = new Rect(200, 200, 600, 600);
int[] angel;
/**
* 用到的角度–比如说第一个角 20 第二个40 第三个60 那么 angelUse就是 0 ,20 ,60 , 120.
* angle就是 20 40 60
*/
int[] angelUse;
/**
* 当前角度
*/
int curAngel;

public void initData(String pieColor, String pieValue) {
this.pieColor = pieColor + “,” + this.pieColor;
this.pieValue = pieValue;
if (pieValue == null || pieValue.length() < 1) {
return;
}
compute();
startAnimation(0, 360);
}

public void initData(String pieValue) {
this.pieValue = pieValue;
if (pieValue == null || pieValue.length() < 1) {
return;
}
compute();
startAnimation(0, 360);
}

public MyPieChart(Context context) {
this(context, null);
}

public MyPieChart(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MyPieChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyPieChart, defStyleAttr, 0);
// int n = a.getIndexCount();
// for (int i = 0; i < n; i++) {
// int attr = a.getIndex(i);
// switch (attr) {
// case R.styleable.MyPieChart_pieCount:
// pieCount = a.getInt(attr, 0);
// break;

// case R.styleable.MyPieChart_pieColor:
// pieColor = a.getString(attr);
// break;

// case R.styleable.MyPieChart_pieValue:
// pieValue = a.getString(attr);
// break;
// }
// }
// color = pieColor.split(“,”);
// value = pieValue.split(“,”);
// a.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true);
// compute();
}

private void compute() {
pieCount = pieValue.split(“,”).length;
color = pieColor.split(“,”);
value = pieValue.split(“,”);
//计算各个值所占的角度
angel = new int[pieCount];
angelUse = new int[pieCount + 1];

for (int l = 0; l < pieCount; l++) {
tValue += Float.parseFloat(value[l]);
}
for (int m = 0; m < pieCount; m++) {
angel[m] = Math.round(Float.parseFloat(value[m]) * 360f / tValue);
}

for (int j = 0; j < pieCount + 1; j++) {
if (j == 0) {
angelUse[j] = 0;
} else {
for (int k = 0; k < j; k++) {
angelUse[j] += angel[k];
}
}

    }
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!backIsDraw) {
backIsDraw = true;
// startAnimation(angelUse[0], 360);
} else {
drawAnimation(canvas);
if (curAngel < 360) {
//invalidate();
} else {
//画其他部分
DrawOhter(canvas);
}
}

}

private void DrawOhter(Canvas canvas) {
for (int i = 0; i < pieCount; i++) {
DrawLine(canvas, i);
DrawText(canvas, i);
}
}

private void DrawText(Canvas canvas, int i) {
mPaint.setColor(Color.RED);
double f = Float.parseFloat(value[i]) / tValue * 100;
BigDecimal b = new BigDecimal(f);
double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//上面3行为四舍五入保留两位小数
canvas.drawText(/“值为” + value[i] + “-” + /f1 + “%”, point3[0], point3[1], mPaint);
}

float[] point1 = new float[2];
float[] point2 = new float[2];
float[] point3 = new float[2];

private void DrawLine(Canvas canvas, int i) {
int angle = (angelUse[i + 1] - angelUse[i]) / 2 + angelUse[i];//内部线条的角度值
if (angle == 0) return;

//Math.toRadians(angle)–把多少度的数字转化成多少分之PI
point1[0] = Radius[0] + (int) Math.round(Math.cos(Math.toRadians(angle)) * R / 2);//x轴
point1[1] = Radius[1] + (int) Math.round(Math.sin(Math.toRadians(angle)) * R / 2);//y轴

point2[0] = point1[0] + (int) Math.round(Math.cos(Math.toRadians(angle)) * 200 / 2);//300是外面第一个点的x减去里面那个点的x
point2[1] = point1[1] + (int) Math.round(Math.sin(Math.toRadians(angle)) * 200 / 2);

if (angle >= 90 && angle <= 270) {
point3[0] = point2[0] - 50;
point3[1] = point2[1];
} else {
point3[0] = point2[0] + 50;
point3[1] = point2[1];
}
mPaint.setColor(Color.BLACK);
canvas.drawLine(point1[0], point1[1], point2[0], point2[1], mPaint);
canvas.drawLine(point2[0], point2[1], point3[0], point3[1], mPaint);
}

private void startAnimation(int startAngel, int Angel) {
final ValueAnimator anima = ValueAnimator.ofObject(new AngelEvaluator(), startAngel, Angel);
anima.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
curAngel = (int) valueAnimator.getAnimatedValue();
invalidate();
}
});
anima.setDuration(2000);
anima.start();
}

/**
* 画扇形
*
* @param canvas
*/
private void drawArc(Canvas canvas) {
for (int i = 0; i < pieCount; i++) {
mPaint.setColor(Color.parseColor(color[i]));
canvas.drawArc(oval, angelUse[i], angel[i], true, mPaint);
// 画弧,第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线

}
}

private void drawAnimation(Canvas canvas) {
// canvas.drawArc(oval, 0, curAngel, true, mPaint);
for (int i = 0; i < pieCount; i++) {
mPaint.setColor(Color.parseColor(color[i]));
// canvas.drawArc(oval, angelUse[i], curAngel - angelUse[i], true, mPaint);
if (angelUse[i] <= curAngel) {
//这么写的原因:当前角度大于等于use才画。(取消上面这个判断会在开始的时候多一块)
canvas.drawArc(oval, angelUse[i], curAngel - angelUse[i], true, mPaint);
}
}
}

int times;

/**
* 画背景
*
* @param canvas
*/
private void drawBackgroud(Canvas canvas) {
mPaint.setColor(Color.BLACK);
canvas.drawRect(mBound, mPaint);
backIsDraw = true;
invalidate();
}

boolean backIsDraw = false;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值