前段时间公司要求要给项目里面用统计图来统计数据的直观信息。之后在GitHub上找到了 MPAndroidChart这个库,
今天不对其原理进行解剖。指记录其用法以及常用的属性设置。围绕柱状图、折线图、和饼状图来给大家解析。。。
一、引言
MPAndroidChart 是 Android 一个强大且容易使用的图表库
- 支持线状图、柱状图、散点图、烛状图、气泡图、饼状图和蜘蛛网状图
- 支持缩放、拖动(平移)、选择和动画
- 适用于 Android 2.2 ( API 8 ) 和以上
- 8种不同的图表类型
- 两轴缩放(支持触摸手势,两轴单独或同时的放缩)
- 拖 / 平移 / 抛(触摸手势)
- Combined-Charts 组合图表(线状、柱状、散点图等)
- 双轴(比如说有两个独立的Y轴数据)
- 高亮显示值(我们可以自定义Popup-views来高亮显示我们选中的值)
- 自定义轴(x轴和y轴)
- 动画(建立x和y轴动画,如开始绘制是的显示动画)
- 自定义(paints、字体、legends、颜色、背景、手势、虚线 …)
二、柱形图、折线图公用属性
不同的统计图表的很多属性都是公用的如:柱状图、折线图
- setDrawBarShadow(false);//–绘制当前展示的内容顶部阴影
- setDrawValueAboveBar(true);//–绘制的图形都在bar顶部
- getDescription().setEnabled(false); // 不显示数据描述
- setPinchZoom(true);//–捏合手势,双指缩放..
- setScaleEnabled(true);//设置是否可以缩放–
- setDrawGridBackground(false);//–绘制中心内容区域背景色.
- getAxisRight().setDrawLabels(false);//禁止显示Y右侧有数据–
- getAxisRight().setDrawAxisLine(false);//禁止显示Y右侧线条–
- setDragEnabled(true);//设置是否拖动–
- setScaleYEnabled(false); //取消Y轴缩放–
- setScaleXEnabled(true);//打开x轴缩放–
- zoomToCenter(2.5f,0f);//让初始显示比例为其总数的一半
1、设置x轴的属性
- setDrawGridLines(false);//–是否绘制竖直分割线.
- setGranularity(1f); // only intervals of 1 day底部label的分割间隙
- setLabelCount(y.length, false); //–对应的当前绘制在底部的label数
- setValueFormatter(new DayAxisValueFormatter(barChart, y)); //设置底部label的文字内容
- setLabelRotationAngle(-25);//设置底部label的旋转角度.
- setAxisMinimum(0); // restrict the x-axis range限制x轴范围
2、设置Y轴的属性
- setLabelCount(5, false); //–绘制Y方向(应该)被显示的数量,第二个参数表示label是否是精准变化,还是近似变化
- setValueFormatter(myAxisValueFormatter);//设置显示的值
- setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);//Y方向文字的位置,在线外侧.(默认在外侧)
- setSpaceTop(15f);//分割线的间距百分比.
- setAxisMinimum(0f); // this replaces setStartAtZero(true)Y方向的起始值.
3、设置图列属性
- .setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);//设置注解的位置在左上方,还有别的值设置不同的位置
- setForm(Legend.LegendForm.CIRCLE);//这是左边显示小图标的形状,还有别的值设置不同的形状
- setEnabled(false);//设置图列隐藏
4、设置每组柱子的个数,或者折线的个数
BarDataSet set1, set2, set3;//每创建一个,就会每组多个柱子,一般会在设置数据里面定义,
(我创建了3个,代表每组有三个柱子)。下面是两种图形对比:
代码如下:
/**
* 柱型统计图数据数据
*/
private void setData(ArrayList<BarEntry> all, ArrayList<BarEntry> finish, ArrayList<BarEntry> unFinish) {
float groupSpace = 0.08f;
float barSpace = 0f; // x4 DataSet
float barWidth = 0.3f; // x4 DataSet
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
BarDataSet set1, set2, set3;
set1 = new BarDataSet(all, isAmountChat ? "总金额" : "事故数量");
set1.setColors(ColorTemplate.MATERIAL_COLORS); //设置柱型颜色
dataSets.add(set1);
if (finish != null&&unFinish!=null) {
set2 = new BarDataSet(finish, isAmountChat ? "已结案金额" : "事故数量");
set3 = new BarDataSet(unFinish, isAmountChat ? "未结案金额 单位(万元)" : "事故数量");
set2.setColor(Color.rgb(124, 36, 98)); //设置柱型颜色set2.setColors(Color.GREEN);
set3.setColors(Color.rgb(215, 96, 12)); //设置柱型颜色
dataSets.add(set2);
dataSets.add(set3);
}
if (!isAmountChat){
barChart.getLegend().setEnabled(false);
}
barChart.getLegend().setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);//设置注解的位置在左上方
barChart.getLegend().setForm(Legend.LegendForm.CIRCLE);//这是左边显示小图标的形状
barChart.animateXY(1000, 2000);//设置动画
BarData data = new BarData(dataSets);
data.setValueTextSize(10f);
data.setValueTypeface(mTfLight);
data.setBarWidth(0.3f);//--设置bar的宽度 ,取值(0-1).
if (finish == null&&unFinish == null) {
data.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return "" + (int) value;
}
});
}else{
data.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return "" + value;
}
});
}
barChart.setData(data);
if (finish != null||unFinish != null){
barChart.getBarData().setBarWidth(barWidth);// specify the width each bar should have指定每个条应有的宽度。
barChart.getXAxis().setAxisMinimum(0); // restrict the x-axis range限制x轴范围
barChart.getXAxis().setAxisMaximum(0 + barChart.getBarData().getGroupWidth(groupSpace, barSpace) * all.size()); //bardata。getgroupwith(…)是一个辅助计算宽度根据提供的参数,每一组都需要
barChart.groupBars(0, groupSpace, barSpace);
barChart.invalidate();
}
}
二、饼状图属性
- setUsePercentValues(false);//设置饼图是否使用百分比
- .getDescription().setEnabled(false);// 不显示数据描述
- .setExtraOffsets(5, 10, 5, 5);
- setDragDecelerationFrictionCoef(0.95f);
- setCenterText(generateCenterSpannableText(centerText));//设置圆盘中间文字的字体
- setExtraOffsets(20.f, 0.f, 20.f, 0.f);
- setDrawHoleEnabled(true);//是否显示饼图中间空白区域,默认显示
- setHoleColor(Color.WHITE);//设置中间圆盘的颜色
- setTransparentCircleColor(Color.TRANSPARENT);//–内圆边框色
- setTransparentCircleAlpha(110);//–内圆边框透明度
- setHoleRadius(58f);//设置中间圆盘的半径,值为所占饼图的百分比
- .setTransparentCircleRadius(61f);//设置中间透明圈的半径,值为所占饼图的百分比
- setDrawCenterText(true);//是否显示圆盘中间文字,默认显示
- setRotationAngle(0);//–绘制的开始位置
- setRotationEnabled(true);//–允许旋转
- setHighlightPerTapEnabled(true);//—允许点击其中某个扇形区域.
- animateY(1400, Easing.EasingOption.EaseInOutQuad);//设置y轴动画
1、设置图列属性
- setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);//设置显示方向
- setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
- setOrientation(Legend.LegendOrientation.HORIZONTAL);
- setDrawInside(false);
- setXEntrySpace(7f);
- setYEntrySpace(0f);
- setYOffset(0f);
2、设置数据的显示方式和属性如:扇形区域内,或扇形区域外
- PieDataSet dataSet = new PieDataSet(entries, “”);//控件右上角的说明文字
- dataSet.setSliceSpace(3f);//设置个饼状图之间的距离
- dataSet.setSelectionShift(10f);// 部分区域被选中时多出的长度
- dataSet.setColors(colors);//颜色
- dataSet.setValueLinePart1OffsetPercentage(100.f);//折线中第一段起始位置相对于区块的偏移量, 数值越大, 折线距离区块越远
- dataSet.setValueLinePart1Length(0.4f);//折线中第一段长度占比
- dataSet.setValueLinePart2Length(0.2f);//折线中第二段长度最大占比
- dataSet.setValueLineColor(Color.rgb(255, 110, 110));//折线颜色
- dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);//数据位置INSIDE_SLICE,OUTSIDE_SLICE 可以显示折线上的数据
- dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);//隐藏扇形区域内的显示数据
3、效果如下图所示
如果想要将数据显示到扇形区域内,不要设置以下属性:
- setYValuePosition();
4、示例代码
/**
* 圆形统计图数据函数
*/
private void setPieData(PieChart mPiechar,ArrayList<PieEntry> entries, ArrayList<Integer> colors, final String anotherType) {
PieDataSet dataSet = new PieDataSet(entries, "");//控件右上角的说明文字
dataSet.setSliceSpace(3f);//设置个饼状图之间的距离
dataSet.setSelectionShift(10f);// 部分区域被选中时多出的长度
dataSet.setColors(colors);
dataSet.setValueLinePart1OffsetPercentage(100.f);//折线中第一段起始位置相对于区块的偏移量, 数值越大, 折线距离区块越远
dataSet.setValueLinePart1Length(0.4f);//折线中第一段长度占比
dataSet.setValueLinePart2Length(0.2f);//折线中第二段长度最大占比
dataSet.setValueLineColor(Color.rgb(255, 110, 110));//折线颜色
dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);//数据位置INSIDE_SLICE,OUTSIDE_SLICE 可以显示折线上的数据
dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
PieData data = new PieData(dataSet);
data.setValueTextSize(11f);//区域文字的大小
data.setValueTextColor(Color.BLACK);//设置区域文字的颜色
data.setValueTypeface(tf);//设置区域文字的字体
data.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
PieEntry pieEntry=(PieEntry)entry;
return anotherType.equals("人员伤亡") ? pieEntry.getLabel() + (int) value +" 人" : pieEntry.getLabel() + (int) value + "件";
}
});
mPiechar.setData(data);
mPiechar.highlightValues(null);
mPiechar.invalidate();
}
二、屏幕适配问题
如果你的统计图是在一个较小的空间里面,那么如果不对高度进行限制,
将会有一部分会被遮挡,这时候要手动设置最大值,否則系统会默认自己根据数据设置图的比例.
如果没有,则忽略
代码如下:
private void setMaxValue() {
YAxis leftAxis = incomeChart.getAxisLeft();
double maxRatio = 0.0;
double maxInterest = 0.0;
if (mTrends != null) {
for (int i = 0; i < mTrends.size(); i++) {
MonthAppreciateProduct.Trend trend = mTrends.get(i);
double ratioDay = trend.getRatioDay();
double interestDay = trend.getInterestDay();
if (ratioDay > maxRatio) maxRatio = ratioDay;
if (interestDay > maxInterest) maxInterest = interestDay;
}
}
if (mType.equals("ratio")) {
if (maxRatio > 0) {
leftAxis.setAxisMaxValue((float) (maxRatio * 1.3));
} else {
leftAxis.setAxisMaxValue(10f);
}
} else {
if (maxInterest > 0) {
leftAxis.setAxisMaxValue((float) (maxInterest * 1.3));//Y轴最大值
} else {
leftAxis.setAxisMaxValue(5f);
}
}
}
这篇就这样了、大家有新发现了,欢迎留言讨论…… 顺便给大家个官方的源码案列,和使用库