有网友发了张图,问我实现的方法。 与一般的柱形图不一样,这张图很特别,相信他要找到现成的,对得上号的图表将不是件易事。
通常图表库实现的不是通常意义上的柱形图,就是单纯的堆积图,很少有这种混在一起展现的情况出现。没得法,要定制才能实现的了。
网友的原图(应当没侵权吧)
利用XCL-Charts实现的效果图:
网友的这张表面看起来,是同一个标签,两个堆积柱形并排放在一起,但依我的经验,要原汁原味让图表库提供这种图是很难的,
参数及数据位置计算很难处理。只能利用现有图表,采用混合方式实现。仔细观察了下,发现实际上只要将两个柱形图并在一起,在柱形高
度上做点手脚就能达到这个效果了。
即,先画高一点那一些柱形图,再绘数据低一层的柱形图。 当然如果数据是变化的,现在高的到时有可能变低,就不能采用这种方法了,
但这张图暂不用考虑这个问题。
定制程序的部份代码如下:
private String TAG = "MultiBarchart201View"; private BarChart chart = new BarChart(); private BarChart chart2 = new BarChart(); //标签轴 private List<String> chartLabels = new LinkedList<String>(); private List<BarData> chartData = new LinkedList<BarData>(); private List<BarData> chartData2 = new LinkedList<BarData>(); private int axisColor = Color.rgb(125, 223, 252); public MultiBarChart01View(Context context) { super(context); // TODO Auto-generated constructor stub initView(); } public MultiBarChart01View(Context context, AttributeSet attrs){ super(context, attrs); initView(); } public MultiBarChart01View(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(); } private void initView() { chartLabels(); chartDataSet(); chartDataSet2(); chartRender(); chartRender2(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //图所占范围大小 chart.setChartRange(w,h); chart2.setChartRange(w,h); } private void chartRender() { try { //设置绘图区默认缩进px值,留置空间显示Axis,Axistitle.... int [] ltrb = getBarLnDefaultSpadding(); chart.setPadding(ltrb[0], ltrb[1], DensityUtil.dip2px(getContext(), 45), ltrb[3]); //数据源 chart.setDataSource(chartData); chart.setCategories(chartLabels); //数据轴 chart.getDataAxis().setAxisMax(2500); chart.getDataAxis().setAxisMin(0); chart.getDataAxis().setAxisSteps(500); //让柱子间没空白 chart.getBar().setBarInnerMargin(0d); //隐藏轴 chart.getDataAxis().setVisible(false); chart.getCategoryAxis().setVisible(false); //将Bar风格设为Fill chart.getBar().setBarStyle(XEnum.BarStyle.FILL); chart.setApplyBackgroundColor(true); chart.setBackgroundColor(Color.rgb(19, 163, 224)); } catch (Exception e) { // TODO Auto-generated catch block Log.e(TAG, e.toString()); } } private void chartRender2() { try { //设置绘图区默认缩进px值,留置空间显示Axis,Axistitle.... int [] ltrb = getBarLnDefaultSpadding(); chart2.setPadding(ltrb[0], ltrb[1], DensityUtil.dip2px(getContext(), 45), ltrb[3]); //显示边框 //chart2.showRoundBorder(); chart2.getBar().setBarStyle(XEnum.BarStyle.FILL); //标题 chart2.setTitle("负债率标准备: 40%~60%"); chart2.addSubtitle("(XCL-Charts Demo)"); chart2.getPlotTitle().getTitlePaint().setColor(axisColor); chart2.getPlotTitle().getSubtitlePaint().setColor(axisColor); //数据源 chart2.setDataSource(chartData2); chart2.setCategories(chartLabels); //轴标题 chart2.getAxisTitle().setLeftAxisTitle("金额"); chart2.getAxisTitle().setLowerAxisTitle("资产负债率"); //数据轴 chart2.getDataAxis().setAxisMax(2500); chart2.getDataAxis().setAxisMin(0); chart2.getDataAxis().setAxisSteps(500); //定义数据轴标签显示格式 chart2.getDataAxis().setLabelFormatter(new IFormatterTextCallBack(){ @Override public String textFormatter(String value) { // TODO Auto-generated method stub Double tmp = Double.parseDouble(value); DecimalFormat df=new DecimalFormat("#0"); String label = df.format(tmp).toString(); return (label); } }); //让柱子间没空白 chart2.getBar().setBarInnerMargin(0d); //轴颜色 chart2.getDataAxis().getAxisPaint().setColor(axisColor); chart2.getCategoryAxis().getAxisPaint().setColor(axisColor); chart2.getDataAxis().getTickMarksPaint().setColor(axisColor); chart2.getCategoryAxis().getTickMarksPaint().setColor(axisColor); chart2.getDataAxis().getTickLabelPaint().setColor(axisColor); chart2.getCategoryAxis().getTickLabelPaint().setColor(axisColor); chart2.getAxisTitle().getLeftAxisTitlePaint().setColor(axisColor); chart2.getAxisTitle().getLowerAxisTitlePaint().setColor(axisColor); //隐藏图例 chart2.getPlotLegend().hideLegend(); } catch (Exception e) { // TODO Auto-generated catch block Log.e(TAG, e.toString()); } } private void chartDataSet() { //标签对应的柱形数据集 List<Double> dataSeriesA= new LinkedList<Double>(); dataSeriesA.add(2400d); dataSeriesA.add(2400d); dataSeriesA.add(2400d); dataSeriesA.add(2400d); dataSeriesA.add(2400d); BarData BarDataA = new BarData("流动资产",dataSeriesA,(int)Color.rgb(58, 191, 247)); List<Double> dataSeriesB= new LinkedList<Double>(); dataSeriesB.add(2000d); dataSeriesB.add(2000d); dataSeriesB.add(2000d); dataSeriesB.add(2000d); dataSeriesB.add(2000d); BarData BarDataB = new BarData("非流动资产",dataSeriesB,(int)Color.rgb(20, 181, 251)); chartData.add(BarDataA); chartData.add(BarDataB); List<Double> dataSeriesAA= new LinkedList<Double>(); dataSeriesAA.add(0d); BarData BarDataAA = new BarData("负债",dataSeriesAA,(int)Color.rgb(38, 137, 176)); List<Double> dataSeriesBB= new LinkedList<Double>(); dataSeriesBB.add(0d); BarData BarDataBB = new BarData("所有者权益",dataSeriesBB,(int)Color.rgb(13, 116, 161)); chartData.add(BarDataAA); chartData.add(BarDataBB); } private void chartDataSet2() { //标签对应的柱形数据集 List<Double> dataSeriesA= new LinkedList<Double>(); dataSeriesA.add(1600d); dataSeriesA.add(1700d); dataSeriesA.add(1800d); dataSeriesA.add(1800d); dataSeriesA.add(1500d); BarData BarDataA = new BarData("负债",dataSeriesA,(int)Color.rgb(38, 137, 176)); List<Double> dataSeriesB= new LinkedList<Double>(); dataSeriesB.add(1500d); dataSeriesB.add(1300d); dataSeriesB.add(1400d); dataSeriesB.add(1200d); dataSeriesB.add(1600d); BarData BarDataB = new BarData("所有者权益",dataSeriesB,(int)Color.rgb(13, 116, 161)); chartData2.add(BarDataA); chartData2.add(BarDataB); } private void chartLabels() { chartLabels.add("20%"); chartLabels.add("40%"); chartLabels.add("60%"); chartLabels.add("80%"); chartLabels.add("100%"); } @Override public void render(Canvas canvas) { try{ chart.render(canvas); chart2.render(canvas); //绘制轴点 float radius = 10f; Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(this.axisColor); canvas.drawCircle(chart2.getPlotArea().getLeft(), chart2.getPlotArea().getBottom(), radius, paint); canvas.drawCircle(chart2.getPlotArea().getRight(), chart2.getPlotArea().getBottom(), radius, paint); canvas.drawCircle(chart2.getPlotArea().getLeft(), chart2.getPlotArea().getTop(), radius, paint); } catch (Exception e){ Log.e(TAG, e.toString()); } }
至此,图就绘制出来了。 代码不长,相信基本能看懂。
特别要说一下代码中的绘制轴点。 在原图中,轴的两端和交叉处都有一个白点。XCL-Charts默认是没有这个功能,但这三个点的位置,
在XCL-Charts中都能取得出来,所以直接在render()中,直接加上三个绘制制circle的代码就行了。图例和轴标题风格有点不同,但这已不是什么大问题了。如果
还要求一样,可从XCL-Charts中依相关函数得到位置后,自定义一个图例和轴标题也不是难事。
发现现在有个性的图太多了,各式各样,好多都没见过,很难考虑得到这些情况,所以图表库的灵活性与定制化越发重要,但我发现很少有人认真去看图表库,
都喜欢瞄瞄有没原样的,没有继续到处找。图表真的很特别时,等着哭吧。 哈哈。
这个例子已收录在XCL-Charts图表库的demo中,有兴趣的可以去看看。
MAIL: xcl_168@aliyun.com
BLOG: http://blog.csdn.net/xcl168
用XCL-Charts定制多柱形堆积图,布布扣,bubuko.com
原文:http://blog.csdn.net/xcl168/article/details/37743265