Android: Use canvas to draw a pie chart (automatically adapts to the number/size of entries). androidcanvas

Source: Internet
Author: User
Tags drawtext

Android: Use canvas to draw a pie chart (automatically adapts to the number/size of entries). androidcanvas

The purpose of this example is to implement a simple pie chart with the following effects:


Features:

1. Easy to use. You can place the content in the xml layout file and set the content in the code, that is:


PieChartView pieChartView = (PieChartView) findViewById (R. id. pie_chart); PieChartView. pieItemBean [] items = new PieChartView. pieItemBean [] {new PieChartView. pieItemBean ("Entertainment", 200), new PieChartView. pieItemBean ("Travel", 100), new PieChartView. pieItemBean ("Learning", 120), new PieChartView. pieItemBean ("Interpersonal Relationship", 160), new PieChartView. pieItemBean ("traffic", 100), new PieChartView. pieItemBean ("catering", 480)}; pieChartView. setPieItems (items );
2. the number, size, line position, and length of entries are adaptive. The left entry is underlined on the left, the right entry is underlined on the right, the text description is aligned with the percentage, and the text "underline" and text length are adaptive. For small entries, the line is automatically extended to avoid text overwriting as much as possible


Core code: 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 screen        screenW = 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 text        linePaint = 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;    @Override    protected 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 pie                piePaint.setColor(mPieColors[i % mPieColors.length]);                float sweep = mPieItems[i].getItemValue() / totalValue * ;                canvas.drawArc(pieOval, start, sweep, true, piePaint);                //draw line away from the pie                float 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 text                String 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 text                canvas.drawText(itemPercentText, percentStartX, percentStartY, textPaint);                //draw text underline                float 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 %  / 90);        switch (a) {            case 0:                return radius;            case 1:                return 180 - radius;            case 2:                return radius - 180;            case 3:                return  - 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;        }    }}




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.