MPAndroidChart的简单封装

因为需求中大部分图表的样式都差不多,只有里面的数据做了变化,而使用图表的时候又需要对图表进行各种各样的配置,所以对图表框架进一步封装是有必要的。
我这里将图表的配置写在一个类中,将常用的方法(数据,图表颜色,描述,等等)令写方法出来设置。。因为使用的是建造者模式,可以根据需求定义。这里封装了线性图、饼状图、柱状图、雷达图。

写了一个数据类ChartValue用来存放所需数据的XY值,然后将数据设置也封装到了,配置类中,图表构建完成后获得图表的View对象,填充到想要的布局中去。

具体实现

ChartView数据类:用来存放X,Y轴值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cn.xiaolongonly.mpchartsample.bean;
/**
* @author xiaolong
* @version v1.0
* @function <描述功能>
* @date 2016/9/22-17:32
*/
public class ChartValue<T> {
public String xVal;
public T yVal;
public ChartValue() {
}
public ChartValue(String xVal, T yVal) {
this.xVal = xVal;
this.yVal = yVal;
}
}

Item项:每个需要的图表构建一个item对象,存放固定配置和数据设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package cn.xiaolongonly.mpchartsample.chart.item;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.ChartData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import java.util.ArrayList;
import java.util.List;
import cn.xiaolongonly.mpchartsample.R;
import cn.xiaolongonly.mpchartsample.bean.ChartValue;
import cn.xiaolongonly.mpchartsample.chart.markview.DataMarkView;
import cn.xiaolongonly.mpchartsample.chart.util.ColorTemplate;
public class LineChartItem extends BaseChartItem {
private String xDesc;
private String yDesc;
private DataMarkView dataMarkView;
public LineChartItem(ChartData cd, Context c, IAxisValueFormatter iAxisValueFormatter) {
super(cd, c, iAxisValueFormatter);
}
public LineChartItem(ChartData cd, Context c, DataMarkView dataMarkView, IAxisValueFormatter iAxisValueFormatter) {
super(cd, c, iAxisValueFormatter);
this.dataMarkView = dataMarkView;
}
@Override
public int getItemType() {
return TYPE_LINECHART;
}
public View getView() {
return getView(null);
}
public String getxDesc() {
return xDesc;
}
public void setxDesc(String xDesc) {
this.xDesc = xDesc;
}
public String getyDesc() {
return yDesc;
}
public void setyDesc(String yDesc) {
this.yDesc = yDesc;
}
@Override
public View getView(View convertView) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.list_item_linechart, null);
holder.chart = (LineChart) convertView.findViewById(R.id.chart);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// apply styling
LineChart lineChart = (LineChart) holder.chart;
lineChart.setBackgroundColor(mContext.getResources().getColor(R.color.chart_bg));
lineChart.getLegend().setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);
lineChart.getLegend().setForm(Legend.LegendForm.CIRCLE);
// 设置无数据文本提示
lineChart.setDescription(null);
// lineChart.setNoDataText(mContext.getResources().getString(R.string.chart_no_data));
// lineChart.setXYDesc(xDesc, yDesc);
if (!xDesc.equals("") || !yDesc.equals("")) {
lineChart.setXYDesc(xDesc, yDesc, 10f, mContext.getResources().getColor(R.color.normal_black_color));
}
//设置单方向和双方向缩放 true x,y方向可以同时控制,false只能控制x方向的缩小放大或者Y方向的缩小放大
lineChart.setPinchZoom(true);
DataMarkView dataMarkView = new DataMarkView(mContext, 0, "");
lineChart.setMarkerView(dataMarkView);
lineChart.setDrawGridBackground(false);
XAxis xAxis = lineChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //定制X轴是在图表上方还是下方。
xAxis.setDrawGridLines(false);
xAxis.setGranularity(1);//放大的时候X值不增多
xAxis.setValueFormatter(mIAxisValueFormatter);
if (dataMarkView != null) {
lineChart.setMarkerView(dataMarkView);
}
YAxis yAxisRight = lineChart.getAxisRight();
yAxisRight.setEnabled(false);
YAxis yAxisLeft = lineChart.getAxisLeft();
yAxisLeft.setAxisMinimum(0);
// set data
lineChart.setData((LineData) mChartData);
// do not forget to refresh the chart
// holder.chart.invalidate();
lineChart.animateX(750);
lineChart.animateY(750);
return convertView;
}
public static class Builder {
private int[] colors = ColorTemplate.PIE_COLORS;
private String[] describles = new String[]{""};
private String xDesc = "";
private String yDesc = "";
private List<List<ChartValue>> charValueLists = new ArrayList<>();
private Context context;
private boolean isFillColor;
private ArrayList<String> labels = new ArrayList<>();
public Builder(Context context) {
this.context = context;
}
public Builder addChartValueList(List<ChartValue> charValueLists) {
this.charValueLists.add(charValueLists);
return this;
}
public Builder setChartValueList(List<List<ChartValue>> charValueLists) {
this.charValueLists = charValueLists;
return this;
}
public Builder setyDesc(String yDesc) {
this.yDesc = yDesc;
return this;
}
public Builder setxDesc(String xDesc) {
this.xDesc = xDesc;
return this;
}
public Builder setDescribles(String[] describles) {
this.describles = describles;
return this;
}
public Builder setColorReses(int[] colorReses) {
this.colors = new int[colorReses.length];
for (int i = 0; i < colors.length; i++) {
colors[i] = context.getResources().getColor(colorReses[i]);
}
return this;
}
public Builder fillColorEnable(boolean isFillColor) {
this.isFillColor = isFillColor;
return this;
}
public LineChartItem build() {
return build(null);
}
public LineChartItem build(DataMarkView dataMarkView) {
List<ILineDataSet> lineDataSets = new ArrayList<>();
for (int listIndexOutside = 0; listIndexOutside < charValueLists.size(); listIndexOutside++) {
ArrayList<Entry> entries = new ArrayList<Entry>();
for (int listIndexInside = 0; listIndexInside < charValueLists.get(listIndexOutside).size(); listIndexInside++) {
entries.add(new Entry((float) listIndexInside, (float) charValueLists.get(listIndexOutside).get(listIndexInside).yVal));
if (listIndexOutside == 0) {
labels.add(charValueLists.get(listIndexOutside).get(listIndexInside).xVal);
}
}
lineDataSets.add(generateLineDataSet(entries, describles[listIndexOutside], colors[listIndexOutside % colors.length]));
}
IAxisValueFormatter iAxisValueFormatter = new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return labels.get((int) value % labels.size());
}
};
LineData cd = new LineData(lineDataSets);
LineChartItem lineChartItem = null;
if (dataMarkView != null) {
lineChartItem = new LineChartItem(cd, context, dataMarkView, iAxisValueFormatter);
} else {
lineChartItem = new LineChartItem(cd, context, iAxisValueFormatter);
}
lineChartItem.setxDesc(xDesc);
lineChartItem.setyDesc(yDesc);
return lineChartItem;
}
private ILineDataSet generateLineDataSet(ArrayList<Entry> entries, String describle, int color) {
LineDataSet dataSet = new LineDataSet(entries, describle);
dataSet.setLineWidth(2.0f);
dataSet.setCircleRadius(3.5f);
dataSet.setDrawCircleHole(true);//填充圆
dataSet.setValueTextSize(9f);
dataSet.setHighlightLineWidth(2.0f);
dataSet.setDrawFilled(isFillColor);
dataSet.setFillAlpha(51);
dataSet.setFillColor(color); //填充色
dataSet.setHighLightColor(color); //选中十字线色
dataSet.setColor(color); //线条颜色
dataSet.setCircleColor(color); //圆点颜色
dataSet.setCircleColorHole(Color.WHITE);
dataSet.setCircleHoleRadius(2.0f);
dataSet.setDrawValues(false);
return dataSet;
}
}
}

当然如果需求图表有其他样式的的话,我觉得也可以把配置信息抽取出来,通过不同的配置来设置不同的样式。

在Activity中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package cn.xiaolongonly.mpchartsample.ui;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
import cn.xiaolongonly.mpchartsample.R;
import cn.xiaolongonly.mpchartsample.base.BaseTitleActivity;
import cn.xiaolongonly.mpchartsample.bean.ChartValue;
import cn.xiaolongonly.mpchartsample.chart.item.LineChartItem;
/**
* @author xiaolong
* @version v1.0
* @function <描述功能>
* @date 2016/12/5-17:32
*/
public class LineChartActivity2 extends BaseTitleActivity {
private RelativeLayout rlContent;
@Override
protected int getLayoutId() {
return R.layout.activity_chart;
}
@Override
protected void initView() {
rlContent = findView(R.id.rlContent);
List<ChartValue> chartValues = new ArrayList<>();
chartValues.add(new ChartValue("11月", 110f));
chartValues.add(new ChartValue("10月", 120f));
chartValues.add(new ChartValue("9月", 100f));
List<ChartValue> chartValues2 = new ArrayList<>();
chartValues2.add(new ChartValue("11月", 155f));
chartValues2.add(new ChartValue("10月", 133f));
chartValues2.add(new ChartValue("9月", 122f));
LineChartItem lineChartItem = new LineChartItem.Builder(this).setxDesc("单位(月)")
.setyDesc("单位(万)").setDescribles(new String[]{"项目支出金额"})
.addChartValueList(chartValues).addChartValueList(chartValues2)
.build();
rlContent.addView(lineChartItem.getView());
}
@Override
protected void setListener() {
}
}

是不是就简单多了只要构建一个Item对象,然后将item对象的图表布局,add到View中去就可以了。

实现效果
实现效果

项目github下载

总结

一直都没想到有一天我也能这么写代码,感觉代码写多了很多东西就懂了。

在最开始的时候老大让我对图表框架进行二次封装,我听的一脸懵逼,经过一段时间的思考,反复对照之前的项目,因为之前的项目的配置都写在继承的图表中,在xml布局中要将图表改成继承的图表,数据导入也写在了Activity类中,感觉代码特别多且杂,后来想到了一句话,多用组合少用继承,现在看来确实,组合的方式会比继承好很多。虽然参考了好多代码,封装的也不怎么样,但是我确实是做到了。

那时候跟同时说我把图表框架封装完的时候,同事说,不会啊封装的不错。对于我这种渣渣来讲就是莫大的安慰了。离自己的目标又近了一步。加油~~

By Xiaolong,每一天都值得被认真对待!