我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!
- 引言
开发会遇到需要的图表,用一个三方库太大比如MPandroidchart,这时候就可以自己来自定义个图表控件,近日我就开发了个饼状图,用来显示各板块占比和信息显示,并加入了动画,某块模块放大,自定义设置板块颜色、字体颜色等功能,可直接拿来使用。
-
设计思路
非动画实现思路,先绘制一个个弧形版块拼接成圆,同一圆心,再绘制一个小点的带透明度的白色圆盖在其上,然后绘制中心的孔,即纯白的圆盖在最上面,最后根据计算,将文字绘制在版块的角平分线上,居在透明圆边和外圆边的中心。 -
代码
onDraw方法中
public void draw(Canvas canvas) {
super.draw(canvas);
//将画布绘成白色
canvas.drawColor(Color.WHITE);
//平移画布,使(0,0)点至中心,便于计算
canvas.translate(getWidth()/2,getHeight()/2);
calculate();
if (showAnimator){
drawByAnim(canvas); //动画绘制
}else {
drawByNormal(canvas); //普通绘制
}
}
这边就是给画笔设置对应颜色,若未设置则随机取色,这边还有个功能就是使该板块有凸起的效果,其实就是采取画布平移(canvas.translate),根据该板块角平分线往外拉一定距离;绘制弧形,使用方法canvas.drawArc(RectF,起始绘制角度,旋转绘制角度,是否包含圆心,画笔);最后将画布恢复到之前保存的状态即为外角平分线平移的状态;将该板块的角度累加到当前角度中去,这样绘制下一板块的起始角度就在这个版块之后了。
/**
* 非动画绘制
*/
private void drawByNormal(Canvas canvas){
//循环绘制各模块
for (int i=0;i<count;i++){
if (0 == getData().get(i).getColor()){
int color = getRandColor();
mOutPaint.setColor(color);
getData().get(i).setColor(color);
}else {
mOutPaint.setColor(getData().get(i).getColor());
}
//计算该板块角度
float sweepAngle = getData().get(i).getData()/sumData*360f;
//保存当前画布状态
canvas.save();
//当前模块角平分线的sin和cos值
if (getData().get(i).isRaised()){
float mathCos = (float) (Math.cos((sweepAngle/2+mCurrentDegree)/180f*Math.PI));
float mathSin = (float) (Math.sin((sweepAngle/2+mCurrentDegree)/180f*Math.PI));
//若该板块设置凸起,平移画布,使其与周边各块产生间距,并突出
canvas.translate(mathCos*mSpace, mathSin*mSpace);
}
//绘制外圆
canvas.drawArc(mRadiusRectF,mCurrentDegree,sweepAngle,true,mOutPaint);
//恢复平移前的状态
canvas.restore();
mCurrentDegree += sweepAngle;
}
//绘制透明圆和中心圆孔
mAlphaPaint.setAlpha((int) (mAlpha*255));
canvas.drawCircle(0,0,mRadius*mAlphaRadiusPercent,mAlphaPaint);
canvas.drawCircle(0,0,mRadius*mHoleRadiusPercent,mHolePaint);
//绘制版块文字
drawTextInner(canvas);
if (showCenterText) {
//绘制中心文字
Paint.FontMetrics metrics = mCenterTextPaint.getFontMetrics();
float textHeight = Math.abs(metrics.descent - metrics.ascent);
canvas.drawText(mCenterText, 0, textHeight / 2 - metrics.descent, mCenterTextPaint);
}
}
- 效果