自定义View实现饼状统计图

前言
在面试中遇到的问题,思考了好久一直没有思路,多次查看资料阅读博客。一般项目中也经常需要这种需求,引用一个三方库, 占用内存太大,还是自己学习写一个案例。 第一次在优快云写博客,如果有不合适的地方请谅解。方便留言写次学习改进。
(一)编写自定义PieCharView类

  • 自定义PieCharView继承View,这个不用解释吧

  • 需要重写两个方法,onSizeChange和onDraw方法,这里是不需要重写onMeasure方法的,因为这个自定义View的视图大小没有发生改变,但是如果需要也是可以重写的。
    执行顺序:onMeasure-》onSizeChange—》onDraw

  • 自定义的View中三个最重要的方法解释:
    onMeasure可以得到并控制本身和子View的大小
    onSizeChange可以得到自身视图View的大小
    onDraw绘制视图View的具体实现

(二)绘制的方法API
绘制弧度

  • canvas.drawArc(oval, starDegree, endDegree, true, mPaint);
    说明:第一个参数代表的是弧形显示的矩形面积。
    第二个参数代表开始的角度数,
    第三个参数代表结束的角度数,
    第四个参数代表是否显示实心,
    第五个参数设计画笔对象。
    绘制文字
  • canvas.drawText(“心跳的频率”, x, y, mPaint);
    说明:第一个参数是要绘制的文字,第二三个参数代表文字绘制开始的左边,第四个参数代表画笔对象。
    (三)本文折线的思路分析:
    使用的方法主要是canvas.drawArc来绘制连续的扇形。
  • 要算出每个范围占有的个数
  • 算出每个范围占有360角度中的度数
  • 下一个扇形开始的角度是上一个扇形开始的角度数加上他图形的角度数。
    (四)自定义View类PieCharView
    package com.free.demo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class PieCharView extends View {

private int mWidth;
private int mHeight;
private String[] pieName;
private RectF oval;
private String[] rangeString;
private List<Integer> listRange = new ArrayList<Integer>();
private List<Integer> listNunber = new ArrayList<Integer>();
private int[] paintColors;
private List<Float> listDegree = new ArrayList<Float>();
private Paint mPaint;

public PieCharView(Context context) {
    this(context,null);
}

public PieCharView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs,0);
}

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

/**
 * @param listNunber   数的集合
 * @param paintColors  画笔颜色集合
 * @param pieName       饼状图名称
 * @param rangeString
 */
public void setData(List<Integer> listNunber, int[] paintColors, String[] pieName, String[] rangeString) {
    this.rangeString = rangeString;
    this.pieName = pieName; this.listNunber.clear();
    this.listNunber.addAll(listNunber);
    this.paintColors = paintColors;
    initDegree();//计算数量占有的度数(比例)
    postInvalidate();
}

private void initDegree() {
    //遍历集合的数据  ,并判断范围
    int num_60 = 0;
    int num60_80 = 0;
    int num80_ = 0;
    for (int number : listNunber) {
        if (number < 60) {
            num_60++;
        } else if (number < 80) {
            num60_80++;
        } else {
            num80_++;
        }
    }
    //比例的个数添加到集合中
    listRange.add(num_60);
    listRange.add(num60_80);
    listRange.add(num80_);
    //计算比例并添加到集合中
    listDegree.add(360f * num_60 / listNunber.size());
    listDegree.add(360f * num60_80 / listNunber.size());
    listDegree.add(360f * num80_ / listNunber.size());

}

public void init() {
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setStrokeWidth(2f);
    mPaint.setColor(Color.WHITE);
    setBackgroundColor(Color.BLACK);
}

@Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //绘制背景颜色和背景线
    drawBackGroudLines(canvas);
    //画饼状图和文字
    drawArcView(canvas);
}

private void drawArcView(Canvas canvas) {
    float starDegree = -10;
    //开始的角度是可以任意的
    mPaint.setTextSize(30);
    //画饼状图
    for (int i = 0; i < listDegree.size(); i++) {
        mPaint.setColor(paintColors[i]);
        //设置线条的颜色,Int类型 Log.e("TAG", "listDegree:" + listDegree.get(i));
        canvas.drawArc(oval, starDegree, listDegree.get(i), true, mPaint);
        starDegree += listDegree.get(i);
        //画文字
        canvas.drawText(pieName[i] + "(" + rangeString[i] + "):" + listRange.get(i) + "次", 10, 450 + i * 50, mPaint); }
}

private void drawBackGroudLines(Canvas canvas) {
    //背景颜色,灰色
    mPaint.setColor(0x80CCCCCC);
    canvas.drawRect(0, 0, mWidth, mHeight, mPaint);
    canvas.drawLine(0, 0, mWidth, 0, mPaint);
    canvas.drawLine(0, mHeight, mWidth, mHeight, mPaint);
}

@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mWidth = getWidth();
    mHeight = getHeight();
    oval = new RectF((mWidth - 400) / 2, 10, (mWidth - 400) / 2 + 400, 410);
}

}
(五)Activity或者Fragment调用自定义View
package com.free.demo;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //数据
    List<Integer> datas = new ArrayList<Integer>();
    datas.add(66);
    datas.add(77);
    datas.add(66);
    datas.add(100);
    datas.add(64);
    datas.add(20);
    datas.add(44);
    datas.add(22);
    datas.add(99);
    datas.add(35);
    datas.add(35);
    datas.add(66);
    datas.add(6);
    datas.add(20);

    // 画笔颜色的数组
    int[] paintColor = {Color.RED, Color.YELLOW, Color.BLUE};
    //饼状图的文字描述
    String[] pieString = {"不及格", "良好", "优秀"};
    //设置的范围描述
    String[] pieRangeString = {"<60", "60-80", ">80"};
    PieCharView pieCharView = (PieCharView) findViewById(R.id.pieCharView);
    pieCharView.setData(datas, paintColor, pieString, pieRangeString);

}
//关闭页面
public void close(View view) {
    finish();
}

}

(五)布局文件是非常简单的

<?xml version="1.0" encoding="utf-8"?>

<com.free.demo.PieCharView
    android:layout_width="match_parent"
    android:layout_height="400dp"
    android:id="@+id/pieCharView"
    />
<Button
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:text="关闭"
    android:onClick="close"
    tools:ignore="OnClick" />

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值