android自定义控件之折线统计图

279 阅读2分钟

android自定义控件之折线统计图

支持负数

package com.wh.andy.robotsystem.custom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class PulseChartView extends View {
    //-------------View相关-------------
    //View自身的宽和高
    private int mHeight;
    private int mWidth;

    //-------------统计图相关-------------
    //x轴的条目
    private int xNum = 63;
    //y轴的条目
    private int yNum = 11;
    //y轴条目之间的距离
    private float ySize;
    //x轴条目之间的距离
    private float xSize;

    
    private String[] xStr = new String[]{"1号", "2号", "3号", "4号", "5号", "6号", "7号", "8号", "9号", "10号", "10号", "10号", "10号", "10号", "10号", "10号", "10号", "10号"};
    private String[] yStr = new String[]{"-150", "-120", "-90", "-60", "-30", "0", "30", "60", "90", "120", "150"};
    //    private String str = "血压趋势";
    //折线表示的最大值,取yStr的最大值
    private int yMaxValue = Integer.parseInt(yStr[yStr.length - 1]);
    //折线真实值
    private int[] yValue = new int[]{-57, -95, -94, -78, -45, -8, 1, 0, -30, -52, -60, -61, -32, -29, -36, -67, -105, -128, -128, -128, -115, -48, 6, 47, 58, 38, 0, -36, -76, -93, -94, -76, -59, -39, -28, -35, -38, -59, -62, -61, -64, -63, -60, -67, -75, -77, -87, -97, -98, -100, -86, -69, -36, -5, 29, 39, 33, 8, -40, -75, -92, -109, -117, -105};

    //-------------画笔相关-------------
    //边框的画笔
    private Paint borderPaint;
    //文字的画笔
    private Paint textPaint;
    //折线的画笔
    private Paint linePaint;
    //黑点的画笔
    private Paint pointPaint;

    //-------------颜色相关-------------
    //边框颜色
    private int mColor = 0xFFC9C9C9;
    //文字颜色
    private int textColor = 0xFF888888;
    //折线颜色
    private int lineColor = 0xFFFA6664;
    //黑点颜色
    private int pointColor = lineColor;

    public PulseChartView(Context context) {
        super(context);
        init();
    }

    public PulseChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PulseChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        initPaint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;

        xSize = (mWidth - 50) / xNum;
        ySize = mHeight / (yNum - 1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化画笔
        initPaint();
        //画布移到左下角,留出100的空间给予文字填充
        canvas.translate(0, mHeight);
        //画边框
        drawBorder(canvas);
        //画黑点
        drawPoint(canvas);
        //画文字
//        drawText(canvas);
        //画折线
        drawLine(canvas);
    }

/*
    private void getMaxValue() {
        int Max, n = 0;
        Max = yValue[0];
        for (int i = 0; i < yValue.length; i++) {
            if (yValue[i] > Max) {
                Max = yValue[i];
                n = i;
            }
        }
        maxValueIndex = n;
    }
*/

    /**
     * 初始化画笔
     */
    private void initPaint() {
        //y轴的长度,11个条目只有10段距离xNum
        //边框画笔
        borderPaint = new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setColor(mColor);
        borderPaint.setStrokeWidth(0.5f);
        //文字画笔
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextSize(20);
        textPaint.setColor(textColor);
        textPaint.setAntiAlias(true);
        //区域画笔
        linePaint = new Paint();
        linePaint.setColor(lineColor);
        linePaint.setAntiAlias(true);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeJoin(Paint.Join.ROUND);
        linePaint.setStrokeWidth(0.5f);
        //黑点画笔
        pointPaint = new Paint();
        pointPaint.setAntiAlias(true);
        pointPaint.setStyle(Paint.Style.STROKE);
        pointPaint.setStrokeWidth(2);
        pointPaint.setColor(pointColor);

    }

    /**
     * 画边框
     *
     * @param canvas
     */
    private void drawBorder(Canvas canvas) {
        Path path = new Path();
        borderPaint.setPathEffect(new DashPathEffect(new float[]{3, 2}, 0));

        for (int i = 0; i < yNum; i++) {
            //一条竖直的线
/*            if (i == 0) {
                path.moveTo(0, -i * ySize);
                path.lineTo(0, -(yNum - 1) * ySize);
            }*/
            //循环水平的线
            path.moveTo(50, -i * ySize);
            path.lineTo(xNum * xSize + 50, -i * ySize);
            canvas.drawPath(path, borderPaint);
            canvas.drawText(yStr[i], 0, -i * ySize, textPaint);
        }
    }

    /**
     * 画黑点
     *
     * @param canvas
     */
    private void drawPoint(Canvas canvas) {
        borderPaint.setStrokeWidth(0.5f);
        for (int i = 0; i <= xNum; i++) {
            //画竖线

            canvas.drawLine((i * xSize) + 50, 0, (i * xSize) + 50, -(ySize * 10), borderPaint);
        }
    }

    /**
     * 画文字
     *
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        //事先说明:文字排版为了好看,这里的20,都为20px的边距
        //x轴的文字
        for (int i = 0; i < xStr.length; i++) {
            //测量文字的宽高
            Rect rect = new Rect();
            textPaint.getTextBounds(xStr[i], 0, xStr[i].length(), rect);
            float textWidth = rect.width();
            float textHeight = rect.height();
            canvas.drawText(xStr[i], i * xSize - textWidth / 2, textHeight + 20, textPaint);
        }
      /*  //y轴的文字
        for (int i = 0; i < yStr.length; i++) {
            //测量文字的宽高
            Rect rect = new Rect();
            textPaint.getTextBounds(yStr[i], 0, yStr[i].length(), rect);
            float textWidth = rect.width();
            float textHeight = rect.height();
            canvas.drawText(yStr[i], -textWidth - 20, i * (-ySize) + (textHeight / 2), textPaint);
        }*/
        //顶部文字
//        canvas.drawText(str, 0, (-ySize) * (yStr.length - 1) - 20, textPaint);
    }

    /**
     * 画折线
     *
     * @param canvas
     */
    private void drawLine(Canvas canvas) {
        Path path = new Path();
        for (int i = 0; i < yValue.length; i++) {
            //计算折线的位置:(当前点的值/最大值)拿到百分比percent
            //用百分比percent乘与y轴总长,就获得了折线的位置
            //这里拿到的百分比一直为0,所以换一种方法,先乘与总长再除与最大值,而且记得加上负号
//            float position = -(yValue[i] * yLastSize / yMaxValue);
            //如果当前值为正数,在第三条线以上,否则在以下
            //判断当前一格所代表的长度 总高度127 一格代表42.3,实际一格是ySize,比值就是ySize/42.3
            float scale = ySize * 10 / 300;
            float position = 0;
            if (yValue[i] > 0) {
                position = (150 + yValue[i]) * scale;
            } else {
                position = (150 - Math.abs(yValue[i])) * scale;
//                position = yValue[i] + (ySize * 3);
            }
            Log.e("position", position + "");
 /*           if (position > 90) {
                position = 90;
            }*/
            if (i == 0) {
                //第一个点需要移动
                path.moveTo(i * xSize + 50, -position);
            } else {
                //其余的点直接画线
                path.lineTo(i * xSize + 50, -position);
            }
            canvas.drawPath(path, linePaint);


        }
    }

}

写的不好,请勿喷