自定义View_一个非常简洁的柱状图
2017-01-14 16:30
190 查看
快过年了,提前祝大家新年快乐哦。马上就可以闲下来休息几天了,好幸福啊。。。不多说了,最近项目中有个地方要用柱状图显示客户的消费情况,本着一名程序员的优秀品质,上gitbub上连续搜罗了有关画图的,不得不说,真心蛮多的,不仅仅功能多,而且很多都已经高度封装,很好用了。但是唯一的缺点就是它们有些功能我们产品用不上,就为了显示一个小柱状图就compile一个别人的项目,有点得不偿失啊。所以我就自己撸了一个,呵呵,撸的蛮简单的。。
如图:
![](https://img-blog.csdn.net/20170114153110349?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20170114163552770?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20170114153126943?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
本着一个菜鸟的气质,也非常羡慕那些会自定义View的人,先不说封装的非常优秀,让人用起来非常顺手;看自定义代码时,各种自定义的属性让人忧郁,我就是这种人,每次下载别人看上去很好的代码,唉,自定义的属性真实太多了,本想顺着他们的思路学习下去,但是很多时候就是看这自定义的高度,宽度,长度,颜色,type值,字体大小值,padding值,margin值…….我就害怕得崩溃了。所以我就想,能不能有些简单的方法让自己能理清思路呢。作为一只有想法的菜鸟,我想就这个柱状图说说自己的看法。
1.显示每个季度/一年中 用户的消费情况
2.科技点击每个季度/一年中任意一个月,可以看到备份比/数值
3.可以自定义颜色
由于不是电商,这个柱状图的很多功能是弱化的,所以我去下载guahub上千star的项目的确有些浪费啊。明确的需求,那就开始写吧。
![](https://img-blog.csdn.net/20170114155334235?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
恩,那么我就先把width,height钉死吧,恩,我就定死你,我先把最重要的写完再写你。
那好啊,我就先画坐标吧。是的,画坐标,画之前,先写死一下:
![](https://img-blog.csdn.net/20170114160000146?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
画坐标的代码我也就不说了,也就一个Paint.drawLine(),你传入一个起始坐标与结束坐标就行,应该来说是简单的了啊。
坐标画完了,那么我就来画我们的柱状图了,这个我想应该也是简单的,就是一个Paint.drawRoundRect(),我想难的还是那个传入的坐标了,
![](https://img-blog.csdn.net/20170114160445412?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这里我们假设所有的柱状图的宽度是一致的,为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,呵呵,恩。
说到这里,相信大家也已经画个大致的样子了吧:
![](https://img-blog.csdn.net/20170114161436539?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1.坐标系的Paint,怎么定义?颜色/字体大小/strokeWidth
2.具状图的Paint, 怎么定义? 颜色[普通颜色/渐变颜色]/字体大小/strokeWidth/显示方式[百分比还是数值]
3.坐标系X轴该显示什么?有没有Paint,显示文字,设置前缀/后缀? 颜色/大小/strokeWidth/位置摆放?
别急,你一个一个来,就像这样:
先标上自己喜欢的颜色,然后再去细致的改吧。当然这是刚刚开始,view的onDraw方法我感觉就像是画家在画画,慢慢去调节。当然啊前提是我们得学习一个常用的技巧,想Paint.draw到底可以draw什么,这个我们得自己知道啊。
微调了坐标系,柱状图,现在还剩下点击颜色发生变化了吧,好吧,那就是OnTouch事件了:
![](https://img-blog.csdn.net/20170114162453296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzc2MjU3Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
那主要是判断我们的MotionEvent是否落在了这个柱状图里面了,如果是那么就修改这个柱状图的Paint中的颜色了,就是这样:
该变画笔的颜色:
好了,基本上就是这样了,还是蛮简单的啊,下面是我定义的属性,也是一点一点加上去的:
基本上都有注释,我想也还算简单的,希望大家喜欢。
代码
好了,上海的下午,太阳落山了还是很冷的,我要去买菜做饭了。。。
如图:
本着一个菜鸟的气质,也非常羡慕那些会自定义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>
基本上都有注释,我想也还算简单的,希望大家喜欢。
代码
好了,上海的下午,太阳落山了还是很冷的,我要去买菜做饭了。。。
相关文章推荐
- [置顶] Android自定义View--自己撸一个柱状图也没那么难
- 一个非常简洁的验证码程序
- ASP.Net中用ViewState存储自定义复杂对象后类型转换的一个问题
- Android自定义View研究(一) -- 一个小Demo
- 自定义View做的一个Clock案例
- 一个非常简洁的验证码程序(转载)
- 一个非常简洁的验证码程序(转载)
- 一个自定义View的实例
- iPhone开发学习笔记005——使用XIB自定义一个UIView,然后将这个view添加到controller的view
- iPhone开发学习笔记005——使用XIB自定义一个UIView,然后将这个view添加到controller的view
- 一个非常简洁有效的判断IP地址格式是否正确的函数,c++代码
- 一个非常简洁高效的JS右键菜单!
- 自定义组件之【柱状图】详解 已封装成View
- 收藏 Dewplayer,一个非常简洁的flash音乐播放器
- 自定义组件之【柱状图】详解 已封装成View
- 一个非常简洁的验证码程序
- Web Service开发实例(转的)——这编描述了如何建立一个webService的实例,写得非常简洁清晰,所以情不自禁地就原文照转了
- 一个非常有用的自定义聚集函数
- 使用XIB自定义一个UIView,然后将这个view添加到controller的view
- 使用XIB自定义一个UIView,然后将这个view添加到controller的view