android实现饼状图

来源:互联网 发布:windows聚焦图片在哪 编辑:程序博客网 时间:2024/06/06 00:23
package com.vanke.easysale.widget.chart;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.graphics.Rect;import android.graphics.RectF;import android.support.annotation.Nullable;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.View;import com.vanke.IntegratedPlatform.manager.R;import com.vanke.easysale.util.DensityUtil;import java.util.ArrayList;/** * 饼状图 * Created by rantao on 2017/8/26. */public class PieChartView extends View {    private int mWidth; // 控件宽度    private int mHeight; // 控件高度    private int mOuterRadius; // 外圆半径    private int mHoleRadius; // 内圆半径    private Paint mPaint; // 画笔    private int[] percentText = {}; // 百分比    private String[] mTexts = {}; // 线条上得文本    private int[] mColors = new int[]{getResources().getColor(R.color.color_e62e3d),            getResources().getColor(R.color.color_ffd633),            getResources().getColor(R.color.color_e5737c),            getResources().getColor(R.color.color_991f29),            getResources().getColor(R.color.color_ff0015)    };    private int mCenterX; // 圆点X坐标    private int mCenterY; // 圆点Y坐标    private float mStartAngle = -90; // 圆弧开始角度    private ArrayList<PiePoint> mPiePoints = new ArrayList<>();    private int sumTextSize;    private String sum = "";    public PieChartView(Context context) {        super(context);    }    public PieChartView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        init();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mCenterX = mWidth / 2;        mCenterY = mHeight / 2;        drawArc(canvas);        drawTextForHoleCenter(canvas);        drawLine(canvas);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width = measure(widthMeasureSpec);        int height = measure(heightMeasureSpec);        setMeasuredDimension(width, height);        updateDimensions(width, height);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        updateDimensions(w, h);    }    private void updateDimensions(int width, int height) {        this.mWidth = width;        this.mHeight = height;    }    private int measure(int measureSpec) {        int result = 0;        int mode = MeasureSpec.getMode(measureSpec);        int size = MeasureSpec.getSize(measureSpec);        switch (mode) {            case MeasureSpec.EXACTLY:                result = size;                break;            case MeasureSpec.AT_MOST:                result = size;                break;            case MeasureSpec.UNSPECIFIED:                break;            default:                break;        }        return result;    }    public void setSum(String sum) {        this.sum = sum;    }    public void setTexts(String[] mTexts) {        this.mTexts = mTexts;    }    public void setPercentText(int[] percentText) {        this.percentText = percentText;        invalidate();    }    /**     * 初始化     */    private void init() {        mOuterRadius = DensityUtil.dip2px(getContext(), 63);        mHoleRadius = DensityUtil.dip2px(getContext(), 38);        mPaint = new Paint();        mPaint.setAntiAlias(true);        sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_18sp);    }    /**     * 画圆弧     *     * @param canvas     */    private void drawArc(Canvas canvas) {        if (null != mPiePoints && mPiePoints.size() > 0) {            mPiePoints.clear();        }        int startX = mCenterX - mOuterRadius;        int endX = mCenterX + mOuterRadius;        int startY = mCenterY - mOuterRadius;        int endY = mCenterY + mOuterRadius;        if (mStartAngle != -90) {            mStartAngle = -90;        }        for (int i = 0; i < percentText.length; i++) {            mPaint.setColor(mColors[i]);            double ratio = ((double) percentText[i] / 100);            float endAngle = (float) (ratio * 360);            PiePoint piePoint = new PiePoint();            piePoint.startAngle = mStartAngle;            piePoint.endAngle = mStartAngle + endAngle;            mPiePoints.add(piePoint);            canvas.drawArc(new RectF(startX, startY, endX, endY), mStartAngle, endAngle - 1, true, mPaint);            mStartAngle = mStartAngle + endAngle; // 下一个开始角度            // 绘制阴影圆心部分            int left = mCenterX - mHoleRadius;            int right = mCenterX + mHoleRadius;            int top = mCenterY - mHoleRadius;            int bottom = mCenterY + mHoleRadius;            Bitmap centerBitmapWithShadow = BitmapFactory.decodeResource(getResources(), R.drawable.ic_piechart_shadow);            canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));            canvas.drawBitmap(centerBitmapWithShadow, null, new RectF(left, top, right, bottom), mPaint);        }    }    /**     * 绘制线条     *     * @param canvas     */    private void drawLine(Canvas canvas) {        for (int i = 0; i < mPiePoints.size(); i++) {            float centerAngle = (mPiePoints.get(i).startAngle + mPiePoints.get(i).endAngle) / 2;            /**             * 分四个象限和四个坐标轴进行判断             */            if (centerAngle > 0 && centerAngle < 90) {                drawBreakLine(canvas, i, 1);            } else if (centerAngle > 90 && centerAngle < 180) {                drawBreakLine(canvas, i, 2);            } else if (centerAngle > 180 && centerAngle < 270) {                drawBreakLine(canvas, i, 3);            } else if ((centerAngle > 270 && centerAngle < 360) || (centerAngle > -90 && centerAngle < 0)) {                drawBreakLine(canvas, i, 4);            } else if (centerAngle == 0) {                drawBreakLine(canvas, i, 5);            } else if (centerAngle == 90) {                drawBreakLine(canvas, i, 6);            } else if (centerAngle == 180) {                drawBreakLine(canvas, i, 7);            } else if (centerAngle == 270) {                drawBreakLine(canvas, i, 8);            }        }    }    private void drawBreakLine(Canvas canvas, int position, int condition) {        float centerAngle = (mPiePoints.get(position).startAngle + mPiePoints.get(position).endAngle) / 2;        int xInArc = 0; // 圆弧中心在圆弧上的X坐标        int yInArc = 0; // 圆弧中心在圆弧上的Y坐标        int breakX = 0; // 拐点X坐标        int breakY = 0; // 拐点Y坐标        int lineEndX = 0; // 横线结束X坐标        int lineEndY = 0; // 横线结束Y坐标        float arcNum;        mPaint.setColor(mColors[position]);        switch (condition) {            case 1:                arcNum = (float) (Math.PI / 180 * centerAngle);                xInArc = (int) (mCenterX + (Math.cos(arcNum) * mOuterRadius));                yInArc = (int) (mCenterY + (Math.sin(arcNum) * mOuterRadius));                breakX = xInArc + DensityUtil.dip2px(getContext(), 5);                breakY = yInArc + DensityUtil.dip2px(getContext(), 5);                lineEndX = breakX + DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX + DensityUtil.dip2px(getContext(), 10), lineEndY);                break;            case 2:                arcNum = (float) (Math.PI / 180 * (centerAngle - 90));                xInArc = (int) (mCenterX - Math.sin(arcNum) * mOuterRadius);                yInArc = (int) (mCenterY + Math.cos(arcNum) * mOuterRadius);                breakX = xInArc - DensityUtil.dip2px(getContext(), 5);                breakY = yInArc + DensityUtil.dip2px(getContext(), 5);                lineEndX = breakX - DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX - DensityUtil.dip2px(getContext(), 10), lineEndY);                break;            case 3:                arcNum = (float) (Math.PI / 180 * (centerAngle - 180));                xInArc = (int) (mCenterX - Math.cos(arcNum) * mOuterRadius);                yInArc = (int) (mCenterY - Math.sin(arcNum) * mOuterRadius);                breakX = xInArc - DensityUtil.dip2px(getContext(), 5);                breakY = yInArc - DensityUtil.dip2px(getContext(), 5);                lineEndX = breakX - DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX - DensityUtil.dip2px(getContext(), 10), lineEndY);                break;            case 4:                arcNum = (float) (Math.PI / 180 * (centerAngle - 270));                xInArc = (int) (mCenterX + Math.sin(arcNum) * mOuterRadius);                yInArc = (int) (mCenterY - Math.cos(arcNum) * mOuterRadius);                breakX = xInArc + DensityUtil.dip2px(getContext(), 5);                breakY = yInArc - DensityUtil.dip2px(getContext(), 5);                lineEndX = breakX + DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX + DensityUtil.dip2px(getContext(), 10), lineEndY);                break;            case 5: // 0度                xInArc = mCenterX + mOuterRadius;                yInArc = mCenterY;                lineEndX = xInArc + DensityUtil.dip2px(getContext(), 70);                lineEndY = yInArc;                breakY = yInArc;                canvas.drawLine(xInArc, yInArc, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX, lineEndY);                break;            case 6: // 90度                xInArc = mCenterX;                yInArc = mCenterY + mOuterRadius;                breakX = xInArc;                breakY = yInArc + DensityUtil.dip2px(getContext(), 10);                lineEndX = xInArc + DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX, lineEndY);                break;            case 7: // 180度                xInArc = mCenterX - mOuterRadius;                yInArc = mCenterY;                lineEndX = xInArc - DensityUtil.dip2px(getContext(), 70);                lineEndY = yInArc;                breakY = yInArc;                canvas.drawLine(xInArc, yInArc, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX, lineEndY);                break;            case 8: // 270度                xInArc = mCenterX;                yInArc = mCenterY - mOuterRadius;                breakX = xInArc;                breakY = yInArc - DensityUtil.dip2px(getContext(), 10);                lineEndX = breakX + DensityUtil.dip2px(getContext(), 70);                lineEndY = breakY;                canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint);                canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint);                canvas.drawCircle(lineEndX, lineEndY, 5, mPaint);                drawTextOnLine(canvas, position, xInArc, breakY, lineEndX);                drawTextForEdge(canvas, position, condition, lineEndX, lineEndY);                break;            default:                break;        }    }    private void drawTextForHoleCenter(Canvas canvas) {        if (percentText.length != 0) {            /**             * 绘制总数动态文本             */            int left = mCenterX - DensityUtil.dip2px(getContext(), 10);            int right = mCenterX + DensityUtil.dip2px(getContext(), 10);            int top = mCenterY + DensityUtil.dip2px(getContext(), 5);            int bottom = mCenterY + DensityUtil.dip2px(getContext(), 15);            Rect rect = new Rect(left, top, right, bottom);            Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();            int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;            mPaint.setTextAlign(Paint.Align.CENTER);            sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_18sp);            mPaint.setTextSize(sumTextSize);            mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_333333));            canvas.drawText(sum, rect.centerX(), baseline, mPaint);            /**             * 绘制"总数"静态文本             */            left = mCenterX - DensityUtil.dip2px(getContext(), 7);            right = mCenterX + DensityUtil.dip2px(getContext(), 7);            top = mCenterY - DensityUtil.dip2px(getContext(), 13);            bottom = mCenterY - DensityUtil.dip2px(getContext(), 3);            rect = new Rect(left, top, right, bottom);            baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;            mPaint.setTextAlign(Paint.Align.CENTER);            sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_12sp);            mPaint.setTextSize(sumTextSize);            mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_999999));            canvas.drawText("总数", rect.centerX(), baseline, mPaint);        }    }    /**     * 绘制线条上的文本     *     * @param canvas     */    private void drawTextOnLine(Canvas canvas, int position, int startX, int startY, int endX) {        int startYTmp =  startY - DensityUtil.dip2px(getContext(), 10);        int endYTmp = startY - DensityUtil.dip2px(getContext(), 5);        Rect rect = new Rect(startX, startYTmp, endX, endYTmp);        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();        int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;        mPaint.setTextAlign(Paint.Align.CENTER);        sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_10sp);        mPaint.setTextSize(sumTextSize);        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_999999));        canvas.drawText(mTexts[position], rect.centerX(), baseline, mPaint);    }    /**     * 绘制线条边缘文本     *     * @param canvas     */    private void drawTextForEdge(Canvas canvas, int position, int codition, int edgeX, int centerY) {        Rect rect = null;        switch (codition) {            case 1:                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX + DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 2:                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX - DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 3:                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX - DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 4:                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX + DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 5: // 0度                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 6: // 90度                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 7: // 180度                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX - DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5));                break;            case 8: // 270度                rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5),                        edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5));                break;            default:                break;        }        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();        int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;        mPaint.setTextAlign(Paint.Align.CENTER);        sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_12sp);        mPaint.setTextSize(sumTextSize);        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_333333));        String percent = percentText[position] + "%";        canvas.drawText(percent, rect.centerX(), baseline, mPaint);    }    class PiePoint {        float startAngle;        float endAngle;    }}
原创粉丝点击