Android绘制学习——基础形状

有些地方待优化处理,这里就没做处理,只是用来学习记录

public class BarChartView extends View {

    private Context context;


    // 画布的位置
    private int XPoint;
    private int YPoint;

    //刻度长度
    private int XScale = 100;
    private int YScale = 60;

    // xy轴的线长
    private int XLength;
    private int YLength;  // 要减去箭头的长度

    // 顶部 底部文字的高度
    private int topTextHight = 60;
    private int bottomTextHight = 100;

    // 设置柱状的高度
    private int height = (int)dipToPx(20);
    private float betweenHeight;

    // 选中的id
    private int chooseId = -1;

    private int MaxDataSize = XLength / XScale;

    private int[] mColors; //对象的颜色
    private List<String> text = new ArrayList<>();  // 底部标题
    private List<RunStatusBean> infos = new ArrayList<>();  // 每个横条的信息


    // 初始化画笔
    private Paint paint;
    private Paint YPaint;
    private Paint YArrowsPaint;
    private Paint headPaint;
    private Paint dottedPaint;
    private Paint datePaint;
    private Paint rectanglePaint;
    private Paint textInRectangle;
    private Paint bottomLinePaint;
    private Paint bottomDiscripPain;




    public BarChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;

        // 初始化每一个级别的颜色
         mColors = new int[]{Color.parseColor("#F47564"),Color.parseColor("#F2AE6D"),Color.parseColor("#4FC3B8") ,Color.parseColor("#64AFF4")};


        // 初始化画笔
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(Color.BLUE);

        // y        YPaint = new Paint();
        YPaint.setStyle(Paint.Style.STROKE);
        YPaint.setAntiAlias(true);
        YPaint.setColor(Color.parseColor("#B0B0B0"));


        // y轴箭头arrows
        YArrowsPaint = new Paint();
        YArrowsPaint.setStyle(Paint.Style.STROKE);
        YArrowsPaint.setAntiAlias(true);
        YArrowsPaint.setColor(Color.parseColor("#B0B0B0"));

        // 头部标题
        headPaint = new Paint();
        headPaint.setTextSize(dipToPx(15));
        headPaint.setColor(Color.parseColor("#B0B0B0"));
        headPaint.setAntiAlias(true);
        headPaint.setTextAlign(Paint.Align.CENTER);

        //虚线
        dottedPaint = new Paint();
        dottedPaint.setStyle(Paint.Style.STROKE);
        PathEffect effects = new DashPathEffect(new float[]{5,5,5,5},1);
        dottedPaint.setAntiAlias(true);
        dottedPaint.setPathEffect(effects);

        //日期文字
        datePaint = new Paint();
        datePaint.setAntiAlias(true);
        datePaint.setTextSize(20);
        datePaint.setTextAlign(Paint.Align.CENTER);

        //矩形
        rectanglePaint = new Paint();
        rectanglePaint.setAntiAlias(true);
        rectanglePaint.setStyle(Paint.Style.FILL);//充满

        // 矩形中的文字
        textInRectangle = new Paint();
        textInRectangle.setTextSize(20);
        textInRectangle.setColor(Color.parseColor("#FFFFFF"));
        textInRectangle.setAntiAlias(true);
        textInRectangle.setTextAlign(Paint.Align.CENTER);

        //底部描述文字的矩形
        bottomLinePaint = new Paint();
        bottomLinePaint.setStyle(Paint.Style.STROKE);
        bottomLinePaint.setStrokeWidth(16);
        bottomLinePaint.setAntiAlias(true);

        // 底部的描述文字
        bottomDiscripPain = new Paint();
        bottomDiscripPain.setColor(Color.parseColor("#A1A6BB"));
        bottomDiscripPain.setAntiAlias(true);
        bottomDiscripPain.setTextSize(26);
        bottomDiscripPain.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    private int measureHeight(int measureSpec) {
        int result = Constant.windowHeight / 3; //结果

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.AT_MOST:  // 子容器可以是声明大小内的任意大小
                result = specSize;
                break;
            case MeasureSpec.EXACTLY:  //父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.  比如EditTextView中的DrawLeft
                result = (int)(Constant.windowHeight*(0.4));
                break;
            case MeasureSpec.UNSPECIFIED:  //父容器对于子容器没有任何限制,子容器想要多大就多大. 所以完全取决于子view的大小
                result = specSize;
                break;
        }
        return result;
    }

    private int measureWidth(int measureSpec) {

        int result = Constant.windowWidth; //默认的size

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.AT_MOST:  // 子容器可以是声明大小内的任意大小
                result = specSize;
                break;
            case MeasureSpec.EXACTLY:  //父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.  比如EditTextView中的DrawLeft
                result = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:  //父容器对于子容器没有任何限制,子容器想要多大就多大. 所以完全取决于子view的大小
                result = (text.size() + 2) * XScale;
                break;
            default:
                break;
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //画布宽高的确定
        int measuredHeight = getMeasuredHeight();
        int measuredWidth = getMeasuredWidth();

        //起画点
        YPoint = measuredHeight;
        XPoint = 60;
        // landy坐标
        landY = YPoint - 16;
        // y坐标长度
        YLength = measuredHeight - bottomTextHight - topTextHight;
        XLength = measuredWidth;
        // y坐标刻度
        YScale = YLength / 5;
        MaxDataSize = XLength / XScale;
        // 设置柱状的间距
        betweenHeight = context.getResources().getDimensionPixelSize(R.dimen.y60);



        /*-----------------------------------------------绘制图型--------------------------------------------*/



        //Y        canvas.drawLine(XPoint, YPoint - bottomTextHight, XPoint, YPoint - YLength - bottomTextHight, YPaint);

        //Y轴箭头
        canvas.drawLine(XPoint, YPoint - YLength - bottomTextHight, XPoint - 3, YPoint-YLength - bottomTextHight + 6, YPaint);
        canvas.drawLine(XPoint, YPoint - YLength - bottomTextHight, XPoint + 3, YPoint-YLength - bottomTextHight + 6, YPaint);

        //X        canvas.drawLine(XPoint, YPoint - bottomTextHight, XPoint + text.size() * XScale, YPoint - bottomTextHight, YPaint);

        // 头标题
        canvas.drawText("单位:kwh",XPoint + dipToPx(30), topTextHight - 20, headPaint);

        //x轴上的虚线
        if(text.size() > 1){
            for(int i=0; i<text.size(); i++){
                if (i == chooseId){
                    dottedPaint.setColor(Color.parseColor("#222328"));
                }else{
                    dottedPaint.setColor(Color.parseColor("#B0B0B0"));
                }

                Path path = new Path();
                path.moveTo(XPoint + (i+1) * XScale, YPoint - bottomTextHight);
                path.lineTo(XPoint + (i + 1) * XScale, YPoint - YLength - bottomTextHight);
                canvas.drawPath(path, dottedPaint);
            }
        }

        // x轴下的文字
        if(text.size() > 1){
            for(int i=0; i<text.size(); i++){
                if (i == chooseId){
                    datePaint.setColor(Color.parseColor("#0786E7"));
                }else{
                    datePaint.setColor(Color.parseColor("#B0B0B0"));
                }
                canvas.drawText(text.get(i),XPoint + (i+1) * XScale,YPoint -bottomTextHight + 40,datePaint);
            }
        }


        // 画矩形(主要计算出矩形的长度)
        for (int i =0; i<infos.size(); i++){
            int heightCount = 0;
            // 颜色控制
            if (infos.get(i).getStatus() == 0){ // 关机
                rectanglePaint.setColor(mColors[0]);
                heightCount = 1;
            }if (infos.get(i).getStatus() == 10){// 正常
                rectanglePaint.setColor(mColors[1]);
                heightCount = 2;
            }if (infos.get(i).getStatus() == 20){// 故障
                heightCount = 3;
                rectanglePaint.setColor(mColors[2]);
            }if (infos.get(i).getStatus() == 30){// 带病运行
                heightCount = 4;
                rectanglePaint.setColor(mColors[3]);
            }

            // 画矩形
            float left  = ((infos.get(i).getStart()-1) + 0.5f) * XScale + XPoint;   // 拿到月份确定left的位置 和 rigth的位置()
            float right  = left + (infos.get(i).getEnd()-infos.get(i).getStart() + 1)*XScale;
            float top  = YPoint - bottomTextHight - heightCount * (betweenHeight) - height ;   // 根据状态判断高度
            float bottom  = YPoint - bottomTextHight - heightCount * (betweenHeight)  ;   // height 为矩形的高度
            RectF oval3 = new RectF(left, top, right, bottom);// 设置个新的长方形
            canvas.drawRoundRect(oval3, 10, 10, rectanglePaint);//第二个参数是x半径,第三个参数是y半径

            // 画文字
            canvas.drawText(infos.get(i).getDesc(), (right - left) / 2 + left, height / 2 + top + 6, textInRectangle);

        }

        //画底部描述线条
        bottomLinePaint.setColor(mColors[3]);

        canvas.drawLine(XPoint, landY, XPoint + landWidth, landY, bottomLinePaint);
        bottomLinePaint.setColor(mColors[2]);
        canvas.drawLine(XPoint + landWidth + landAmong + textWidth(landText[0],26,bottomLinePaint), landY
                , XPoint + (landWidth *2) + landAmong + textWidth(landText[0],26,bottomLinePaint), landY, bottomLinePaint);
        bottomLinePaint.setColor(mColors[1]);
        canvas.drawLine(XPoint + (landWidth *2) + (landAmong *2) + textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
                , landY, XPoint + (landWidth *3) + (landAmong *2)+ textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint), landY, bottomLinePaint);
        bottomLinePaint.setColor(mColors[0]);
        canvas.drawLine(XPoint + (landWidth *3) + (landAmong *3)+ 2*textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
                , landY, XPoint + (landWidth *4) + (landAmong *3)+2*textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
                , landY, bottomLinePaint);

        //画底部描述文字
        canvas.drawText(landText[0]
                , excursion + XPoint + landWidth + (landAmong + textWidth(landText[0],26,bottomDiscripPain))/ 2
                , landY + 8, bottomDiscripPain);
        canvas.drawText(landText[1]
                , excursion + XPoint + (landWidth * 2) + (landAmong + textWidth(landText[1],26,bottomDiscripPain))/ 2 + (landAmong + textWidth(landText[0],26,bottomDiscripPain))
                ,landY + 8, bottomDiscripPain);
        canvas.drawText(landText[2]
                , excursion + XPoint + (landWidth * 3) +(landAmong + textWidth(landText[0],26,bottomDiscripPain))+(landAmong + textWidth(landText[1],26,bottomDiscripPain))+((landAmong + textWidth(landText[2],26,bottomDiscripPain))/2)
                ,landY +8,bottomDiscripPain);
        canvas.drawText(landText[3]
                ,excursion + XPoint + (landWidth * 4) +(landAmong + textWidth(landText[0],26,bottomDiscripPain))+(landAmong + textWidth(landText[1],26,bottomDiscripPain))+(landAmong + textWidth(landText[2],26,bottomDiscripPain))+((landAmong + textWidth(landText[3],26,bottomDiscripPain))/2)
                ,landY +8,bottomDiscripPain);
    }

    private int landWidth = 60;
    private int landAmong = 60;
    private int excursion = -14;  // land文字向x方向的偏移量
    private float landY;
    private String [] landText = {"正常","带病运行","故障","关机"};

    private float dipToPx(float dip) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int)(dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    public void setHeight(int height) {    // 设置柱状高度
        this.height = height;
    }

    public void setText(List<String> text) {   // 设置底部标题
        this.text = text;
        this.invalidate();
    }

    public void setInfos(List<RunStatusBean> infos) {   // 设置info
        this.infos = infos;
        this.invalidate();
    }

    private float textWidth(String string, int size, Paint paint){
        paint.setTextSize(size);
        float textWidth =paint.measureText(string + "");
        return textWidth;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值