美文网首页
自定义View实例--->饼图

自定义View实例--->饼图

作者: 谢尔顿 | 来源:发表于2018-02-27 15:17 被阅读14次

效果图


分析:从上面效果图我们可以知道该View由饼图右侧的矩形文字组成,接下来我们具体分析如何用代码实现。
  • 首先我们肯定需要构建一个实体类,用来描述自定义View时需要的属性值;
public class PieChartBean {
    public int mColor;      //填充的颜色值

    public float sweepAngle;    //绘制圆弧是用到的sweepAngle,构建实例的时候不需要赋值
    public String name;         //文字的内容
    public float value;         //具体数值,用来计算sweepAngle和文字右侧的数值

    public PieChartBean(int color, String name, float value) {
        mColor = color;
        this.name = name;
        this.value = value;
    }
}
  • 绘制View
    我们可以利用canvas的drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) 绘制左侧的饼图,该方法我们需要关注的参数是开始角度startAngle和扫过的角度值sweepAngle,而sweepAngle可以有startAngle计算得知。矩形我们可以用方法 drawRect(RectF rect, Paint paint)绘制,文字我们可以用drawText(String text, float x, float y,Paint paint) 绘制,下面看看完整代码:
public class PieChartView extends View {
    private  Context mContext;
    private ArrayList<PieChartBean> beanList;
    private RectF mRectF;
    private Paint mPaint;
    private int mRWidth;
    private int mRHeight;
    private int diameter;
    private float sumValue = 0;
    private float startRotateDegree;//每个圆弧的起始角度
    private RectF iRectF;
    private int mMargin = 40;//矩形和圆的距离
    private int mRectWidth = 100;//矩形宽度
    private int textY;//绘制文字的y坐标
    private int mRectHeight = 50;//矩形高度

    public PieChartView(Context context) {
        //在代码中new PieChartView会调用这个构造函数
        this(context,null);
    }

    public PieChartView(Context context, AttributeSet attrs) {
        //InflateLayoutManager时会调用这个构造函数
        this(context, attrs, 0);
    }

    public PieChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        init();
    }

    private void init() {
        beanList = new ArrayList<>();
        mRectF = new RectF();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int wMode = MeasureSpec.getMode(widthMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        int wSize = MeasureSpec.getSize(widthMeasureSpec);
        int hSize = MeasureSpec.getSize(heightMeasureSpec);

        switch (wMode){
            case MeasureSpec.EXACTLY:
                //相当于match_parent或者一个具体值
                mRWidth = wSize;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED://很少会用到不考虑
                //相当于wrap_content
                mRWidth = (int) DpUtil.dp2px(mContext,400f);
                break;
        }
         switch (hMode){
            case MeasureSpec.EXACTLY:
                //相当于match_parent或者一个具体值
                mRHeight = hSize;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED://很少会用到不考虑
                //相当于wrap_content
                mRHeight = (int) DpUtil.dp2px(mContext,200f);
                break;
        }

        setMeasuredDimension(mRWidth,mRHeight);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        diameter = Math.min(mRWidth,mRHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mRectF.set(0,0,diameter,diameter);
        canvas.translate((mRWidth-diameter)/8,(mRHeight - diameter) / 2);

        if (beanList.size() > 0 && Float.compare(sumValue,0.0f) != 0){
            for (int i = 0; i < beanList.size(); i++) {
                PieChartBean pieChartBean = beanList.get(i);
                //画圆弧
                mPaint.setColor(pieChartBean.mColor);
                canvas.drawArc(mRectF,startRotateDegree,pieChartBean.sweepAngle,true,mPaint);
                //下一个圆弧的起始角度
                startRotateDegree += pieChartBean.sweepAngle;
                //画矩形和文字
                drawRectAndText(canvas,pieChartBean);
            }
        }
        //绘制完之后必须要让textY置为0,否则会有问题的
        textY = 0;
    }

    private void drawRectAndText(Canvas canvas, PieChartBean pieChartBean) {
        iRectF = new RectF();
        //设置画矩形的范围
        float left = diameter + mMargin;
        float right = diameter + mMargin + mRectWidth;
        float bottom = textY + mRectHeight;
        iRectF.set(left,textY,right,bottom);
        canvas.drawRect(iRectF,mPaint);
        //设置颜色
        mPaint.setColor(pieChartBean.mColor);
        //设置文字大小
        mPaint.setTextSize(40);
        //画文字
        canvas.drawText(pieChartBean.name + "("+new DecimalFormat(".00").format(pieChartBean.value/sumValue*100)+"%)"
                ,right + 10, textY + 40, mPaint);
        textY += mRectHeight;
    }

    /**
     * 饼状图添加数据
     * @param list
     */
    public void setData(List<PieChartBean> list){
        if (list == null || list.size()<=0)
            return;
        //计算总值
        for (int i = 0; i < list.size(); i++) {
            PieChartBean pieChartBean = list.get(i);
            sumValue += pieChartBean.value;
        }
        //计算每条数据的sweepAngle
        for (int i = 0; i < list.size(); i++) {
            PieChartBean pieChartBean = list.get(i);
            pieChartBean.sweepAngle = pieChartBean.value / sumValue * 360;
            beanList.add(pieChartBean);
        }
        //刷新界面
        invalidate();
    }

    /**
     * 设置绘制第一个圆弧的起始角度
     * @param startDegree
     */
    public void setStartDegree(float startDegree){
        this.startRotateDegree = startDegree;
        invalidate();
    }
}
  • 实体类的构建并给view的数据赋值

    private void initPieData() {
        PieChartBean bean1 = new PieChartBean(Color.parseColor("#f14033"), "郭瑜", 80);
        PieChartBean bean2 = new PieChartBean(Color.parseColor("#e6870b"), "李旭", 30);
        PieChartBean bean3 = new PieChartBean(Color.parseColor("#0fc2c2"), "南南", 50);
        PieChartBean bean4 = new PieChartBean(Color.parseColor("#29b117"), "石瑾", 60);
        PieChartBean bean5 = new PieChartBean(Color.parseColor("#1b75e4"), "羊角", 20);
        PieChartBean bean6 = new PieChartBean(Color.parseColor("#e746d4"), "亚琴", 30);
        PieChartBean bean7 = new PieChartBean(Color.parseColor("#df0d30"), "贾祺", 60);
        List<PieChartBean> list = new ArrayList<>();
        list.add(bean1);
        list.add(bean2);
        list.add(bean3);
        list.add(bean4);
        list.add(bean5);
        list.add(bean6);
        list.add(bean7);
        //设置绘制圆弧的起始角度
        mPieChartView.setStartDegree(90f);
        mPieChartView.setData(list);
    }

源码都在这上面在此就不贴了。

相关文章

网友评论

      本文标题:自定义View实例--->饼图

      本文链接:https://www.haomeiwen.com/subject/odxmxftx.html