二、关于自定义view的文章:柱状图

时间:2022-12-21 05:55:19

背景:许多时候,第三方满足不了实际UI需求,就需要自己手绘柱状图。

安卓画图是延续了java的绘制方法。但,由于市面上机型的多样性,绘制的困难主要在于适配。

一、柱状图效果图:

二、关于自定义view的文章:柱状图

二、状图图要点:

分析需求根据以上效果图:
1、可见4根彩色渐变色柱;可自行设置为多根动态绘制。本例未处理,仅按照4根柱实现。
2、每根柱根据实际情况占比,背景有五根刻度线均分自定义view,显示高度占比;
3、柱状底部显示月份文案;文案居中对齐。
4、柱状顶部显示数量文案;与柱状图居中对齐,保持一定高度。

三、技术要点:

首先常识性科普,上篇文章写到继承Framelayout布局的自定义view。与上篇文章不同,本文继承view。
继承view一般来说均是通过cavnas绘制。因此通过重写view的ondraw方法。

1、适配各个机型屏幕:

int width = getWidth();
int height = getHeight();
通过以上方法获取自定view的宽度,与getMeasuredWidth方法结果相同。
通过屏幕宽度、高度计算各自位置,这样所有手机机型都会展示效果一致。
例如:绘制背景横线:
//        绘制横向线条
        for (int i=1;i<6;i++){
        canvas.drawLine(dp2px(setPadding), height*i/6, width - dp2px(setPadding), height*i/6
                , xLinePaint);
        }
例如:绘制柱状图:通过绘制矩形来绘制柱状图,左上右下四个点(准确说就是,左上角坐标和右下角坐标点位置)。第8行,渐变色简单处理直接用色条作为一个背景即可。
for(int i = 0; i < 4; i++){
            showText = 0;
            Rect rect = new Rect();// 柱状图的形状
            rect.left = dp2px(setPadding) + (width-dp2px(setPadding*2))*3*i/10;
            rect.right = dp2px(setPadding) + (width-dp2px(setPadding*2))*3*i/10 + (width-dp2px(setPadding*2))/10;
            rect.top = (int) (height*5/6 - yPercents.get(i)*(height*4/6));
            rect.bottom = height*5/6;
            canvas.drawBitmap(bitmap,null,rect, paint);
        }

2、文字位置:底部和柱形图上面的文字位置需要计算字符串的所占宽度

例如:绘制底部月份:其中第5行,显示通过month画笔绘制的文字x M o n t h.get(i)的宽度。然后第6行文字的起始位置的时候横坐标用等比位置减去文字宽度的一半。如:一月则为屏幕均分12等分位置减去文字宽度的一半即一月文字开始位置。(此处setpadding值为两侧留白距离,可忽略)
// 设置底部的月份
        for (int i = 0; i < 4; i++) {
            // text, baseX, baseY, textPaint
            if (xMonths.get(i)!=null){
            float textWidth = monthPaint.measureText(xMonths.get(i)+"");
            canvas.drawText(xMonths.get(i), dp2px(setPadding) + (width-dp2px(setPadding*2))*3*i/10 +(width-dp2px(setPadding*2))/20 - textWidth/2, height-height/24
                    , monthPaint);
            }
        }
又例如:柱状图顶部文字:
canvas.drawText(getDatahandle(text.get(i)) + "",rect.left + (width-dp2px(setPadding*2))/20 - textWidth/2, rect.top - dp2px(10), titlePaint);

3、将数据对外开放,通过外部设置数据给自定view。

例如:一定注意第5行的invalidate方法,设置完数据后一定要调用。否则修改数据后不会调用ondraw方法重绘。
public void setViewData(ArrayList<String> xMonths, ArrayList<String> text, ArrayList<Double> yPercents){
        this.xMonths = xMonths;
        this.text = text;
        this.yPercents = yPercents;
        invalidate();
    }

gitHub项目地址: 点击打开链接