Android自定义控件实现饼状图

本文实现一个如图所示的控件,包括两部分,左边的饼状图和中间的两个小方块,及右边的两行文字

实现起来比较简单,只是一些绘图API的调用

核心代码在onDraw函数里边,对静态控件进行绘制即可

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

/**

* 饼状图的x坐标

*/

float centreX= getWidth()/5;

/**

* 饼状图的y坐标

*/

float centreY= getHeight()/2;

/**

* 文字的大小

*/

float textSize=getHeight()/7;

float width=(float)getWidth();

float height=(float)getHeight();

/**

* 中间小正方形边长的一半

*/

float halfSmallRec =((float)getHeight())*3/70;

percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);

/**

* 求饼状图的半径

*/

radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);

/**

* 构建一个正方形,饼状图是这个正方形的内切圆

*/

rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));

/**

* 设置饼状图画笔的颜色,先绘制大球占的比例

*/

piePaint.setColor(mBigBallColor);

/* The arc is drawn clockwise. An angle of 0 degrees correspond to the

* geometric angle of 0 degrees (3 o'clock on a watch.)*/

/* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/

/**

* 绘制大球的扇形图,float startAngle起始角度的0度的位置在3点钟方向

* 因此大球的扇形图要从12点钟开始绘制,所以起始角度为270度

*/

canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);

/**

* 换种颜色,开始绘制小球占的饼状图

*/

piePaint.setColor(mSmallBallColor);

/**

* 起始角度就是12点钟加上360度乘以大球占的比例,12点钟转换为起始角度为270度

*/

canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);

颜色更改为大球的颜色*/

piePaint.setColor(mBigBallColor);

/**

* 绘制上边的小方块,也就是大球的方块

*/

canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);

/**

* 更改画笔颜色为小球颜色

*/

piePaint.setColor(mSmallBallColor);

/**

* 绘制下边的小方块即小球的小方块

*/

canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);

/**

* 开始绘制文字,先设置文字颜色

*/

textPaint.setColor(getResources().getColor(typedValue.resourceId));

/**

* 设置问题大小

*/

textPaint.setTextSize(textSize);

/**

* 大球数量

*/

String strBig = strBigBallName + mBigBallNumber;

/**

* 测量文字宽度

*/

float textBigWidth =textPaint.measureText(strBig);

Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();

/**

* 绘制上边大球数量

*/

canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);

/**

* 小球数量

*/

String strSmall = strSmallBallName + mSmallBallNumber;

/**

* 测量文字宽度

*/

float textUnderWidth=textPaint.measureText(strSmall);

/**

* 绘制下边的小球数量

*/

canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);

/**

* 更改画笔颜色,开始绘制百分比

*/

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

String strBigPercent =" ("+ mPercentBigBall +")";

/**

* 测量大球百分比文字宽度

*/

float bigPercent =textPaint.measureText(strBigPercent);

/**drawText(String text, float x, float y, Paint paint)

* 绘制文字的API,四个参数分别是文字内容,起始绘制x坐标,起始绘制y坐标,画笔

* 以为设置了居中绘制,因此穿进去的xy坐标为文字的中心点

*/

canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);

/**

* 同样的道理绘制小球的百分比

*/

String strSmallPercent =" ("+ mPercentSmallBall +")";

float smallPercent =textPaint.measureText(strSmallPercent);

canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);

}

Canvas 绘制文本时,使用FontMetrics对象,计算位置的坐标。参考:使用FontMetrics对象计算位置坐标

设置文字绘制以中心为起点开始绘制

textPaint.setTextAlign(Paint.Align.CENTER);

x的坐标好计算,y坐标需要按需使用FontMetrics几个属性即可

完整代码如下:

public class PieHalfView extends View {

/**

* 左边饼状图的画笔

*/

private Paint piePaint;

/**

* 右边文字的画笔

*/

private Paint textPaint;

/**

* 饼状图的半径

*/

private float radius;

private RectF rectf;

/**

* 饼状图中第一个扇形占整个圆的比例

*/

private float percent;

/**

* 深浅两种颜色

*/

private int mBigBallColor, mSmallBallColor;

/**

* 大小球的数量

*/

private int mBigBallNumber;

private int mSmallBallNumber;

/**

* 大小球所占的百分比

*/

private String mPercentBigBall;

private String mPercentSmallBall;

/**

* 动态获取属性

*/

private TypedValue typedValue;

/**

* 中间的文字信息

*/

private String strBigBallName;

private String strSmallBallName;

public PieHalfView(Context context) {

super(context);

init(context);

}

public PieHalfView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public PieHalfView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context);

}

private void init(Context context) {

/**

* 设置饼状图画笔

*/

piePaint =new Paint();

piePaint.setAntiAlias(true);

piePaint.setStyle(Paint.Style.FILL);

/**

* 设置文字画笔

*/

textPaint=new Paint();

textPaint.setStyle(Paint.Style.STROKE);

textPaint.setAntiAlias(true);

textPaint.setTextAlign(Paint.Align.CENTER);

/**

* 下边设置一些默认的值,如果调用者没有传值进来的话,用这些默认值

*/

mBigBallColor = 0xFF9CCA5D;

mSmallBallColor =0xFF5F7048;

/*TypedValue:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.*/

typedValue=new TypedValue();

context.getTheme().resolveAttribute(R.attr.maintextclor,typedValue,true);

mBigBallNumber =1;

mSmallBallNumber =3;

mPercentBigBall ="40%";

mPercentSmallBall ="60%";

strBigBallName =getResources().getString(R.string.big);

strSmallBallName =getResources().getString(R.string.small);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

/**

* 饼状图的x坐标

*/

float centreX= getWidth()/5;

/**

* 饼状图的y坐标

*/

float centreY= getHeight()/2;

/**

* 文字的大小

*/

float textSize=getHeight()/7;

float width=(float)getWidth();

float height=(float)getHeight();

/**

* 中间小正方形边长的一半

*/

float halfSmallRec =((float)getHeight())*3/70;

percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);

/**

* 求饼状图的半径

*/

radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);

/**

* 构建一个正方形,饼状图是这个正方形的内切圆

*/

rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));

/**

* 设置饼状图画笔的颜色,先绘制大球占的比例

*/

piePaint.setColor(mBigBallColor);

/* The arc is drawn clockwise. An angle of 0 degrees correspond to the

* geometric angle of 0 degrees (3 o'clock on a watch.)*/

/* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/

/* 绘制大球的扇形图,float startAngle起始角度的0度的位置在3点钟方向

* 因此大球的扇形图要从12点钟开始绘制,所以起始角度为270度*/

canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);

/**

* 换种颜色,开始绘制小球占的饼状图

*/

piePaint.setColor(mSmallBallColor);

/**

* 起始角度就是12点钟加上360度乘以大球占的比例,12点钟转换为起始角度为270度

*/

canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);

/**

* 颜色更改为大球的颜色*/

piePaint.setColor(mBigBallColor);

/**

* 绘制上边的小方块,也就是大球的方块

*/

canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);

/**

* 更改画笔颜色为小球颜色

*/

piePaint.setColor(mSmallBallColor);

/**

* 绘制下边的小方块即小球的小方块

*/

canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);

/**

* 开始绘制文字,先设置文字颜色

*/

textPaint.setColor(getResources().getColor(typedValue.resourceId));

/**

* 设置问题大小

*/

textPaint.setTextSize(textSize);

/**

* 大球数量

*/

String strBig = strBigBallName + mBigBallNumber;

/**

* 测量文字宽度

*/

float textBigWidth =textPaint.measureText(strBig);

Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();

/**

* 绘制上边大球数量

*/

canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);

/**

* 小球数量

*/

String strSmall = strSmallBallName + mSmallBallNumber;

/**

* 测量文字宽度

*/

float textUnderWidth=textPaint.measureText(strSmall);

/**

* 绘制下边的小球数量

*/

canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);

/**

* 更改画笔颜色,开始绘制百分比

*/

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

String strBigPercent =" ("+ mPercentBigBall +")";

/**

* 测量大球百分比文字宽度*/

float bigPercent =textPaint.measureText(strBigPercent);

/** drawText(String text, float x, float y, Paint paint)

* 绘制文字的API,四个参数分别是文字内容,起始绘制x坐标,起始绘制y坐标,画笔

* 以为设置了居中绘制,因此穿进去的xy坐标为文字的中心点

*/

canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);

/*

* 同样的道理绘制小球的百分比

*/

String strSmallPercent =" ("+ mPercentSmallBall +")";

float smallPercent =textPaint.measureText(strSmallPercent);

canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);

}

public void setPercent(float percent1){

this.percent =percent1;

invalidate();

}

public void setColor(int mBigBallColor,int mSmallBallColor){

this.mBigBallColor =mBigBallColor;

this.mSmallBallColor =mSmallBallColor;

invalidate();

}

public void setOverRunner(String bigPecent, String smallPercent, int big, int small,

int bigColor, int smallColor){

this.mPercentBigBall = bigPecent;

this.mPercentSmallBall = smallPercent;

this.mBigBallNumber = big;

this.mSmallBallNumber = small;

this.mBigBallColor = bigColor;

this.mSmallBallColor = smallColor;

invalidate();

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Android自定义控件实现饼状图 的全部内容, 来源链接: utcz.com/p/241486.html

回到顶部