您的位置:首页 > 其它

自定义View_一个非常简洁的柱状图

2017-01-14 16:30 190 查看
快过年了,提前祝大家新年快乐哦。马上就可以闲下来休息几天了,好幸福啊。。。不多说了,最近项目中有个地方要用柱状图显示客户的消费情况,本着一名程序员的优秀品质,上gitbub上连续搜罗了有关画图的,不得不说,真心蛮多的,不仅仅功能多,而且很多都已经高度封装,很好用了。但是唯一的缺点就是它们有些功能我们产品用不上,就为了显示一个小柱状图就compile一个别人的项目,有点得不偿失啊。所以我就自己撸了一个,呵呵,撸的蛮简单的。。

如图:







本着一个菜鸟的气质,也非常羡慕那些会自定义View的人,先不说封装的非常优秀,让人用起来非常顺手;看自定义代码时,各种自定义的属性让人忧郁,我就是这种人,每次下载别人看上去很好的代码,唉,自定义的属性真实太多了,本想顺着他们的思路学习下去,但是很多时候就是看这自定义的高度,宽度,长度,颜色,type值,字体大小值,padding值,margin值…….我就害怕得崩溃了。所以我就想,能不能有些简单的方法让自己能理清思路呢。作为一只有想法的菜鸟,我想就这个柱状图说说自己的看法。

我想做一个怎么样的控件

在android中写个自定义控件并不是为了好玩[我是这么理解的],大多数自定义控件的诞生,都是与我们的业务逻辑相关的,然后通过代码抽象,提取了一个符合多种场合的东西。所以,我们的控件,不管是找的,还是自己写的,到底能不能实现自己业务中的功能。说到这里,简单列举我自己项目中柱状图要的功能:

1.显示每个季度/一年中 用户的消费情况

2.科技点击每个季度/一年中任意一个月,可以看到备份比/数值

3.可以自定义颜色

由于不是电商,这个柱状图的很多功能是弱化的,所以我去下载guahub上千star的项目的确有些浪费啊。明确的需求,那就开始写吧。

开始

这就是说自己的想法了,我先特么不管onMeasure(),onSizeChanged(),我先画个草图再说,这对我onDraw觉得是有帮助的:



恩,那么我就先把width,height钉死吧,恩,我就定死你,我先把最重要的写完再写你。

那好啊,我就先画坐标吧。是的,画坐标,画之前,先写死一下:



画坐标的代码我也就不说了,也就一个Paint.drawLine(),你传入一个起始坐标与结束坐标就行,应该来说是简单的了啊。

坐标画完了,那么我就来画我们的柱状图了,这个我想应该也是简单的,就是一个Paint.drawRoundRect(),我想难的还是那个传入的坐标了,



这里我们假设所有的柱状图的宽度是一致的,为mItemWidth , 另外还有一个就是两个柱状图之间的距离值,我们也假设他们之间的距离也是一样的,那么也可以设置mItemBetWidth;可以看出结论如下:

n * mItemWidth + (n+1) * mItemBetWidth = View的宽度 - View.paddingLeft - View.paddingRight ;这里的n就是我们设置的要显示的柱状图的个数,唉,先不管了,设置n=12吧。这个mItemWidth与mItemBetWdith怎么办,还能咋办,先让他们相等嘛,如果测试妹妹说不行,我们改还不行吗?

那么我们得到的结论就是 mItemWidth = (View.宽度 - View.paddingLeft - View.paddingRight ) / (2 * n + 1) ;

好了,宽度确定了,高度呢?? 先设置假的啊,用random,呵呵,恩。

说到这里,相信大家也已经画个大致的样子了吧:



细节

写到这里,自定义View已经完成了很多一部分,为了能让我们的View拿得出手,需要定义一些细节,哪些细节呢?举个例子啊:

1.坐标系的Paint,怎么定义?颜色/字体大小/strokeWidth

2.具状图的Paint, 怎么定义? 颜色[普通颜色/渐变颜色]/字体大小/strokeWidth/显示方式[百分比还是数值]

3.坐标系X轴该显示什么?有没有Paint,显示文字,设置前缀/后缀? 颜色/大小/strokeWidth/位置摆放?

别急,你一个一个来,就像这样:

mTextPaint = new Paint();
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(mTextColor);
mTextPaint.setTextSize(mTextSize);
Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
mTextBottomHeight = metrics.ascent + metrics.descent;

mChartPaint = new Paint();
mChartPaint.setStyle(Paint.Style.FILL);
mChartPaint.setAntiAlias(true);
mChartPaint.setColor(mStartChartViewColor);

mTextTopPaint = new Paint();
mTextTopPaint.setStyle(Paint.Style.FILL);
mTextTopPaint.setAntiAlias(true);
mTextTopPaint.setTextSize(mTopTextSize);
mTextTopPaint.setColor(mTopTextColor);

mCoordinatePaint = new Paint();
mCoordinatePaint.setColor(Color.RED);
mCoordinatePaint.setAntiAlias(true);
mCoordinatePaint.setStrokeWidth(4);


先标上自己喜欢的颜色,然后再去细致的改吧。当然这是刚刚开始,view的onDraw方法我感觉就像是画家在画画,慢慢去调节。当然啊前提是我们得学习一个常用的技巧,想Paint.draw到底可以draw什么,这个我们得自己知道啊。

微调了坐标系,柱状图,现在还剩下点击颜色发生变化了吧,好吧,那就是OnTouch事件了:



那主要是判断我们的MotionEvent是否落在了这个柱状图里面了,如果是那么就修改这个柱状图的Paint中的颜色了,就是这样:

private boolean contains(float x, float y) {
for (int i = 1; i <= mChartItemCount; i++) {
int tempValue = mValues.get(i - 1);

RectF rectF = new RectF();
rectF.top = mTextLocationHeight + mChartPaddingTop - tempValue * mHeight * 1.0f / (mMaxValue - mMinValue);
rectF.left = (i - 1) * mBetweenWidth + (i - 1) * mChartWidth;
rectF.right = i * (mBetweenWidth + mChartWidth) + mChartWidth;
rectF.bottom = mTextLocationHeight + mChartPaddingTop;

if (rectF.contains(x, y)) {
mCurrentIndex = i - 1;
return true;
}
}
return false;
}


该变画笔的颜色:

mTextPaint.setColor(mCurrentIndex == i - 1 ? mChooseColor : mTopTextColor);
canvas.drawText(result, rectF.left + mChartWidth / 2 - width / 2, rectF.top - 10, mTextTopPaint);


好了,基本上就是这样了,还是蛮简单的啊,下面是我定义的属性,也是一点一点加上去的:

<declare-styleable name="CustomChartView">

<!--底部文字颜色 -->
<attr name="text_color" format="color"/>
<!--底部文字大小 -->
<attr name="text_size" format="dimension"/>
<!--底部文字后缀 当然你可以定义前缀-->
<attr name="text_suffix" format="string"/>

<!--chartView开始显示的颜色-->
<attr name="chart_start_color" format="color"/>
<!--chartView结束显示的颜色-->
<attr name="chart_end_color" format="color"/>
<!--chartView选中的颜色-->
<attr name="chart_choose_color" format="color"/>
<!--chartView的圆角大小-->
<attr name="chart_view_circle_radius" format="integer"/>

<!--顶部文字的颜色-->
<attr name="text_top_color" format="color"/>
<!--顶部文字大小-->
<attr name="text_top_size" format="dimension"/>
<!--顶部文字显示方式 百分比还是数值-->
<attr name="text_top_type" format="enum">
<enum name="percent" value="1"/>
<enum name="value" value="2"/>
</attr>

<!--显示chartView的个数-->
<attr name="chart_item_count" format="integer"/>
<!--最大值-->
<attr name="chart_max_value" format="integer"/>
<!--最小值-->
<attr name="chart_min_value" format="integer"/>

<!--chartView显示图与View顶部的距离-->
<attr name="chart_padding_top" format="dimension"/>
<!--chartView显示图与View底部的距离-->
<attr name="chart_padding_bottom" format="dimension"/>

</declare-styleable>


基本上都有注释,我想也还算简单的,希望大家喜欢。

代码

好了,上海的下午,太阳落山了还是很冷的,我要去买菜做饭了。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: