安卓饼状图设置软件_Android扇形图(饼状图)

关于Android的图形控件,市场上是有很多的开源库的

我个人用的比较多的就是:MPAndroidChart,个人感觉挺好用的,但是有写时候,满足不了需求,就需要自己去写了。

先看看我们的效果图:

TIM图片20171010170541.jpg

先要想好画一个扇形的步骤

1:画圆

2:画扇形

3:画白色边框

4:画指示线和文字

第一步画圆就不讲解了,直接说第二步

画扇形:

/**

* 画扇形

* @param canvas

*/

private void initPie(Canvas canvas) {

int anglesSize = list.size();

if (list != null && anglesSize > 0){

float pieStart = START_DEGREE;

if (mSweep == null) {

mSweep = new Float[list.size()];

}

for (int i = 0;i < anglesSize; i++){

piePaint.setColor(getResources().getColor(list.get(i).getColor()));

canvas.drawArc(rectF, pieStart, mSweep[i], true, piePaint); //扇形

canvas.drawArc(rectF, pieStart, mSweep[i], true, outerLinePaint); //边框线

pieStart += mSweep[i];

}

}

}

看到里面是根据扇形的角度去绘制出来扇形的大小,然后根据扇形的角度绘制每个paint的颜色,边框也是根据角度来定的。

然后就开始画指示线和文字:

private void initLineAndText(Canvas canvas, float statrAngles, float angles, int color, String text) {

float stopX,stopY;

float ceterX = getMeasuredWidth() / 2;

float ceterY = getMeasuredHeight() / 2;

linePaint.setColor(getResources().getColor(color));

textPaint.setColor(getResources().getColor(color));

// 半径加上多出的20个像素的位置,去根据角度算出 转点的X,Y轴

float cosX = (float) Math.cos(( 2 * statrAngles + angles) / 2 * Math.PI /180 );

float sinY = (float) Math.sin((2 * statrAngles + angles) / 2 * Math.PI /180 );

stopX = (radius + dip2px(10)) * cosX;

stopY = (radius + dip2px(10)) * sinY;

//扇形弧边的中点的X,Y 为起点,然后算出中间点的角度,加上半径+10个像素 得出终点的XY轴,

canvas.drawLine(ceterX + (radius - dip2px(10)) * cosX, ceterY + (radius - dip2px(10))* sinY,stopX+ceterX,stopY+ceterY,linePaint);

Rect rect = new Rect();

textPaint.getTextBounds(text, 0, text.length(), rect);

int h = rect.height();

int w = rect.width();

//画第二根线,第二个根线的起点是第一根线的终点,然后终点,根据X轴来定直接加25个像素

//如果是右边,减去25个像素

//文字的位置,Y轴根据第二根线的Y轴+文字的高度的一半,这样就能居中 X轴,左边加30个像素,根第二个线的有5个像素的距离

//文字如果在右边,减去文字的宽度 - 30个像素

if (stopX > 0) {

//50为横线的长度 60 为文字的偏移量

canvas.drawLine(ceterX +stopX, ceterY +stopY, ceterX +stopX + dip2px(25), ceterY +stopY, linePaint);

canvas.drawText(text, 0, text.length(), ceterX +stopX +dip2px(30) ,ceterY +stopY + h/2, textPaint);

} else {

canvas.drawLine(ceterX +stopX, ceterY +stopY, ceterX +stopX - dip2px(25), ceterY +stopY, linePaint);

canvas.drawText(text, 0, text.length(), ceterX +stopX - w - dip2px(30) ,ceterY+stopY + h/2 , textPaint);

}

}

这个在哪里调用的,当然不是在onDraw方法里面,是在画扇形的里面,因为里面的角度是根据扇形的角度来定的。具体代码就不详细讲解了,注释已经说的很明白了,在initPie的for循环里面去调用这个方法。

这样,我们的扇形就已经出来了。

为了效果,加上了动画

private float PIE_ANIMATION_VALUE = 100;

private class PieChartAnimation extends Animation {

@Override

protected void applyTransformation(float interpolatedTime, Transformation t) {

super.applyTransformation(interpolatedTime, t);

mSweep = new Float[list.size()];

if (interpolatedTime < 1.0f) {

for (int i = 0; i < list.size(); i++) {

//根据传进来的比例,算出在圆中所占的角度

mSweep[i] = list.get(i).getAngle() * interpolatedTime / PIE_ANIMATION_VALUE * 360;

}

} else {

for (int i = 0; i < list.size(); i++) {

mSweep[i] = list.get(i).getAngle() /PIE_ANIMATION_VALUE * 360;

}

}

invalidate();

}

}

其实这个扇形是根据另外一个大佬写的,我在上面改了

大佬的传送门:http://www.jianshu.com/p/f50dbae3a07f

好了,附上源码:

public class PieChart extends View {

private Paint paint; //圆画笔

private Paint piePaint; //扇形画笔

private Paint outerLinePaint; //轮廓画笔

private Paint linePaint; //指示线

private Paint textPaint; //文字画笔

private float radius; //半径

private static final int PAINT_COLOR = 0xed3535;

private static final float OUTER_LINE_WIDTH = 3f;

private static final float START_DEGREE = -90f; //开始绘制角度

//饼状图动画效果

private float X;

private float Y;

private RectF rectF;

private Float mSweep[];

//饼状图动画效果

private PieChartAnimation mAnimation;

private Context context;

private List list;

public PieChart(Context context) {

this(context,null);

}

public PieChart(Context context, @Nullable AttributeSet attrs) {

this(context, attrs,0);

}

public PieChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

this.context = context;

init();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

radius = Math.min(getMeasuredWidth(),getMeasuredHeight()) / 3;

X = getMeasuredWidth() / 2;

Y = getMeasuredHeight() / 2;

rectF.left = X - radius;

rectF.top = Y - radius;

rectF.right = X + radius;

rectF.bottom = Y + radius;

}

private void init() {

paint = new Paint();

paint.setColor(PAINT_COLOR);

paint.setAntiAlias(true);

paint.setAlpha(110);

paint.setStyle(Paint.Style.FILL);

piePaint = new Paint();

piePaint.setStyle(Paint.Style.FILL);

piePaint.setAntiAlias(true);

piePaint.setAlpha(255);

outerLinePaint = new Paint();

outerLinePaint.setAntiAlias(true);

outerLinePaint.setAlpha(255);

outerLinePaint.setStyle(Paint.Style.STROKE);

outerLinePaint.setStrokeWidth(OUTER_LINE_WIDTH);

outerLinePaint.setColor(Color.WHITE);

rectF = new RectF();

linePaint = new Paint();

linePaint.setAntiAlias(true);

linePaint.setStrokeWidth(4);

textPaint = new Paint();

textPaint.setAntiAlias(true);

textPaint.setStrokeWidth(30);

textPaint.setTextSize(25);

mAnimation = new PieChartAnimation();

mAnimation.setDuration(2000);

}

public void setDate(List list){

this.list = list;

if (mSweep == null){

mSweep = new Float[list.size()];

}

if (mAnimation != null)

setAnimation(mAnimation);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

initPie(canvas);

}

/**

* 画扇形

* @param canvas

*/

private void initPie(Canvas canvas) {

int anglesSize = list.size();

if (list != null && anglesSize > 0){

float pieStart = START_DEGREE;

if (mSweep == null) {

mSweep = new Float[list.size()];

}

for (int i = 0;i < anglesSize; i++){

piePaint.setColor(getResources().getColor(list.get(i).getColor()));

canvas.drawArc(rectF, pieStart, mSweep[i], true, piePaint); //扇形

canvas.drawArc(rectF, pieStart, mSweep[i], true, outerLinePaint); //边框线

initLineAndText(canvas, pieStart, mSweep[i], list.get(i).getColor(), list.get(i).getValuer());

pieStart += mSweep[i];

}

}

}

/**

* 画指示线 和文字

* @param canvas

* @param text

*/

private void initLineAndText(Canvas canvas, float statrAngles, float angles, int color, String text) {

float stopX,stopY;

float ceterX = getMeasuredWidth() / 2;

float ceterY = getMeasuredHeight() / 2;

linePaint.setColor(getResources().getColor(color));

textPaint.setColor(getResources().getColor(color));

// 半径加上多出的20个像素的位置,去根据角度算出 转点的X,Y轴

float cosX = (float) Math.cos(( 2 * statrAngles + angles) / 2 * Math.PI /180 );

float sinY = (float) Math.sin((2 * statrAngles + angles) / 2 * Math.PI /180 );

stopX = (radius + dip2px(10)) * cosX;

stopY = (radius + dip2px(10)) * sinY;

//扇形弧边的中点的X,Y 为起点,然后算出中间点的角度,加上半径+10个像素 得出终点的XY轴,

canvas.drawLine(ceterX + (radius - dip2px(10)) * cosX, ceterY + (radius - dip2px(10))* sinY,stopX+ceterX,stopY+ceterY,linePaint);

Rect rect = new Rect();

textPaint.getTextBounds(text, 0, text.length(), rect);

int h = rect.height();

int w = rect.width();

//画第二根线,第二个根线的起点是第一根线的终点,然后终点,根据X轴来定直接加25个像素

//如果是右边,减去25个像素

//文字的位置,Y轴根据第二根线的Y轴+文字的高度的一半,这样就能居中 X轴,左边加30个像素,根第二个线的有5个像素的距离

//文字如果在右边,减去文字的宽度 - 30个像素

if (stopX > 0) {

//50为横线的长度 60 为文字的偏移量

canvas.drawLine(ceterX +stopX, ceterY +stopY, ceterX +stopX + dip2px(25), ceterY +stopY, linePaint);

canvas.drawText(text, 0, text.length(), ceterX +stopX +dip2px(30) ,ceterY +stopY + h/2, textPaint);

} else {

canvas.drawLine(ceterX +stopX, ceterY +stopY, ceterX +stopX - dip2px(25), ceterY +stopY, linePaint);

canvas.drawText(text, 0, text.length(), ceterX +stopX - w - dip2px(30) ,ceterY+stopY + h/2 , textPaint);

}

}

/**

* dip转为 px

*/

private int dip2px(float dipValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dipValue * scale + 0.5f);

}

private float PIE_ANIMATION_VALUE = 100;

private class PieChartAnimation extends Animation {

@Override

protected void applyTransformation(float interpolatedTime, Transformation t) {

super.applyTransformation(interpolatedTime, t);

mSweep = new Float[list.size()];

if (interpolatedTime < 1.0f) {

for (int i = 0; i < list.size(); i++) {

//根据传进来的比例,算出在圆中所占的角度

mSweep[i] = list.get(i).getAngle() * interpolatedTime / PIE_ANIMATION_VALUE * 360;

}

} else {

for (int i = 0; i < list.size(); i++) {

mSweep[i] = list.get(i).getAngle() /PIE_ANIMATION_VALUE * 360;

}

}

invalidate();

}

}

}

PieChartBean实体类参数:

private String valuer; //说明

private Float angle; //占的大小

private Integer color; //颜色值

好了,自己动手试试吧。所有的源码都在这里。用的时候,直接穿一个list进来就可以了...

你离成功只差一个动手的距离

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值