本文实例讲述了Android编程实现canvas绘制饼状统计图功能。分享给大家供大家参考,具体如下:
本例的目的是实现一个简单的饼状统计图,效果如下:

特点:
1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即:
PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart);PieChartView.PieItemBean[] items = new PieChartView.PieItemBean[]{new PieChartView.PieItemBean("娱乐", 200),new PieChartView.PieItemBean("旅行", 100),new PieChartView.PieItemBean("学习", 120),new PieChartView.PieItemBean("人际关系", 160),new PieChartView.PieItemBean("交通", 100),new PieChartView.PieItemBean("餐饮", 480)};pieChartView.setPieItems(items);
2.条目数量,大小及折线位置,长度均自适应。左侧条目往左侧划线,右侧条目往右侧划线,文字描述与百分比居中对齐,并且文字“下划线”与文字长度自适应。对于很小的条目,将自动将折线延长以尽可能避免文字遮盖
核心代码:PieChartView.Java:
public class PieChartView extends View {private int screenW, screenH;/** * The paint to draw text, pie and line. */private Paint textPaint, piePaint, linePaint;/** * The center and the radius of the pie. */private int pieCenterX, pieCenterY, pieRadius;/** * The oval to draw the oval in. */private RectF pieOval;private float smallMargin;private int[] mPieColors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.CYAN};private PieItemBean[] mPieItems;private float totalValue;public PieChartView(Context context) {super(context);init(context);}public PieChartView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public PieChartView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {//init screenscreenW = ScreenUtils.getScreenW(context);screenH = ScreenUtils.getScreenH(context);pieCenterX = screenW / 2;pieCenterY = screenH / 3;pieRadius = screenW / 4;smallMargin = ScreenUtils.dp2px(context, 5);pieOval = new RectF();pieOval.left = pieCenterX - pieRadius;pieOval.top = pieCenterY - pieRadius;pieOval.right = pieCenterX + pieRadius;pieOval.bottom = pieCenterY + pieRadius;//The paint to draw text.textPaint = new Paint();textPaint.setAntiAlias(true);textPaint.setTextSize(ScreenUtils.dp2px(context, 16));//The paint to draw circle.piePaint = new Paint();piePaint.setAntiAlias(true);piePaint.setStyle(Paint.Style.FILL);//The paint to draw line to show the concrete textlinePaint = new Paint();linePaint.setAntiAlias(true);linePaint.setStrokeWidth(ScreenUtils.dp2px(context, 1));}//The degree position of the last item arc"s center.private float lastDegree = 0;//The count of the continues "small" item.private int addTimes = 0;@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (mPieItems != null && mPieItems.length > 0) {float start = 0.0f;for (int i = 0; i < mPieItems.length; i++) {//draw piepiePaint.setColor(mPieColors[i % mPieColors.length]);float sweep = mPieItems[i].getItemValue() / totalValue * 360;canvas.drawArc(pieOval, start, sweep, true, piePaint);//draw line away from the piefloat radians = (float) ((start + sweep / 2) / 180 * Math.PI);float lineStartX = pieCenterX + pieRadius * 0.7f * (float) (Math.cos(radians));float lineStartY = pieCenterY + pieRadius * 0.7f * (float) (Math.sin(radians));float lineStopX, lineStopY;float rate;if (getOffset(start + sweep / 2) > 60) {rate = 1.3f;} else if (getOffset(start + sweep / 2) > 30) {rate = 1.2f;} else {rate = 1.1f;}//If the item is very small, make the text further away from the pie to avoid being hided by other text.if (start + sweep / 2 - lastDegree < 30) {addTimes++;rate += 0.2f * addTimes;} else {addTimes = 0;}lineStopX = pieCenterX + pieRadius * rate * (float) (Math.cos(radians));lineStopY = pieCenterY + pieRadius * rate * (float) (Math.sin(radians));canvas.drawLine(lineStartX, lineStartY, lineStopX, lineStopY, linePaint);//write textString itemTypeText = mPieItems[i].getItemType();String itemPercentText = Utility.formatFloat(mPieItems[i].getItemValue() / totalValue * 100) + "%";float itemTypeTextLen = textPaint.measureText(itemTypeText);float itemPercentTextLen = textPaint.measureText(itemPercentText);float lineTextWidth = Math.max(itemTypeTextLen, itemPercentTextLen);float textStartX = lineStopX;float textStartY = lineStopY - smallMargin;float percentStartX = lineStopX;float percentStartY = lineStopY + textPaint.getTextSize();if (lineStartX > pieCenterX) {textStartX += (smallMargin + Math.abs(itemTypeTextLen - lineTextWidth) / 2);percentStartX += (smallMargin + Math.abs(itemPercentTextLen - lineTextWidth) / 2);} else {textStartX -= (smallMargin + lineTextWidth - Math.abs(itemTypeTextLen - lineTextWidth) / 2);percentStartX -= (smallMargin + lineTextWidth - Math.abs(itemPercentTextLen - lineTextWidth) / 2);}canvas.drawText(itemTypeText, textStartX, textStartY, textPaint);//draw percent textcanvas.drawText(itemPercentText, percentStartX, percentStartY, textPaint);//draw text underlinefloat textLineStopX = lineStopX;if (lineStartX > pieCenterX) {textLineStopX += (lineTextWidth + smallMargin * 2);} else {textLineStopX -= (lineTextWidth + smallMargin * 2);}canvas.drawLine(lineStopX, lineStopY, textLineStopX, lineStopY, linePaint);lastDegree = start + sweep / 2;start += sweep;}}}public PieItemBean[] getPieItems() {return mPieItems;}public void setPieItems(PieItemBean[] pieItems) {this.mPieItems = pieItems;totalValue = 0;for (PieItemBean item : mPieItems) {totalValue += item.getItemValue();}invalidate();}private float getOffset(float radius) {int a = (int) (radius % 360 / 90);switch (a) {case 0:return radius;case 1:return 180 - radius;case 2:return radius - 180;case 3:return 360 - radius;}return radius;}static class PieItemBean {private String itemType;private float itemValue;PieItemBean(String itemType, float itemValue) {this.itemType = itemType;this.itemValue = itemValue;}public String getItemType() {return itemType;}public void setItemType(String itemType) {this.itemType = itemType;}public float getItemValue() {return itemValue;}public void setItemValue(float itemValue) {this.itemValue = itemValue;}}}
完整实例代码点击此处
本站下载。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。