背景:许多时候,第三方满足不了实际UI需求,就需要自己手绘柱状图。
安卓画图是延续了java的绘制方法。但,由于市面上机型的多样性,绘制的困难主要在于适配。
一、柱状图效果图:
二、状图图要点:
分析需求根据以上效果图:
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方法重绘。
gitHub项目地址: 点击打开链接
public void setViewData(ArrayList<String> xMonths, ArrayList<String> text, ArrayList<Double> yPercents){ this.xMonths = xMonths; this.text = text; this.yPercents = yPercents; invalidate(); }
gitHub项目地址: 点击打开链接