Android:使用canvas繪製餅狀統計圖(自動適應條目數量/大小),androidcanvas

來源:互聯網
上載者:User

Android:使用canvas繪製餅狀統計圖(自動適應條目數量/大小),androidcanvas

本例的目的是實現一個簡單的餅狀統計圖,效果如下:

        

特點:

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 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 * 360;                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 % 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;        }    }}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.