Android 图表开源框架之MPAndroidChart LineChart折线图(一)
Android 图表开源框架之MPAndroidChart LineChart折线图(二)
Android 图表开源框架之MPAndroidChart LineChart之常用自定义设置功能
源码下载地址:MPAndroidChart3_0_1.zip https://mp.csdn.net/console/upDetailed
Android 图表开源框架之MPAndroidChart LineChart折线图,v3.0.1版本,MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,应用起来非常灵活。MPAndroidChart显得更为轻巧和简单,拥有常用的图表类型:线型图、饼图、柱状图和散点图。
一.效果图:
二.快速实现:
1 | implementation 'com.github.PhilJay:MPAndroidChart:v3.0.1' |
1.主函数代码:
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 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.format.DateFormat; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Button; import com.example.m1571.mympandroidchart.utils.CustomXValueFormatter; import com.example.m1571.mympandroidchart.utils.MyMarkerView; import com.example.m1571.mympandroidchart.utils.MyMarkersView; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; 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.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.PercentFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** * * 图表开源框架 * https://blog.csdn.net/qq_43332570/article/details/103180779 * *https://blog.csdn.net/qq_26787115/article/details/53611373 * * * https://www.jb51.net/article/142778.htm * https://www.jb51.net/article/141344.htm * https://www.jb51.net/article/96508.htm * <p> * https://github.com/hdodenhof/CircleImageView */ public class ChartActivity extends AppCompatActivity { ArrayList<PieEntry> pieEntryList = new ArrayList();//数据列表 ArrayList<Integer> colors = new ArrayList();//颜色列表 private LineChart lineChart; float datas[] = {14f,15f,16f,17f,16f,16f}; float datas2[] = {17f,16f,15f,14f,17f,14f}; //在MPAndroidChart一般都是通过List<Entry>对象来装数据的 final List<Entry> entries = new ArrayList<Entry>(); final List<Entry> entries2 = new ArrayList<Entry>(); final List<String> yRightList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chart); lineChart = (LineChart) findViewById(R.id.lineChart); List<Integer> mylist = new ArrayList<>(); // for (int i = 0; i < 10; i++) { // mylist.add(i); // } mylist.add(1); mylist.add(8); mylist.add(3); mylist.add(7); mylist.add(2); mylist.add(8); mylist.add(5); mylist.add(0); mylist.add(1); mylist.add(6); setData(mylist); //解决滑动冲突 // lineChart.setOnTouchListener(new View.OnTouchListener() // { // @Override // public boolean onTouch(View v, MotionEvent event) // { // switch (event.getAction()) // { // case MotionEvent.ACTION_DOWN: // { // scrollview.requestDisallowInterceptTouchEvent(true); // break; // } // case MotionEvent.ACTION_CANCEL: // case MotionEvent.ACTION_UP: // { // scrollview.requestDisallowInterceptTouchEvent(false); // break; // } // } // return false; // } // }); } /** * 初始化曲线图表 * * @param list 数据集 */ public void setData(final List<Integer> list){ //显示边界 lineChart.setDrawBorders(false); //设置数据 List<Entry> entries = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { entries.add(new Entry(i, (float) list.get(i))); } //一个LineDataSet就是一条线 LineDataSet lineDataSet = new LineDataSet(entries, "sgf"); //线颜色 lineDataSet.setColor(Color.parseColor("#F15A4A")); //线宽度 lineDataSet.setLineWidth(1.6f); //不显示圆点 lineDataSet.setDrawCircles(false); //线条平滑 lineDataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER); lineDataSet.setDrawFilled(true); lineDataSet.setFillAlpha(50); lineDataSet.setFillColor(Color.RED); // dataSet.setFillColor(R.drawable.gradient_chart_bg2); int[] colors = { getResources().getColor(R.color.colorAccent), getResources().getColor(android.R.color.white) }; // dataSet.setFillColor(getResources().getColor(R.drawable.gradient_chart_bg2)); //设置曲线下方渐变的阴影 lineDataSet.setDrawFilled(true); lineDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_gradient_bg_shape)); lineDataSet.setLineWidth(1.75f); // 线宽 lineDataSet.setCircleSize(5f);// 显示的圆形大小 lineDataSet.setDrawCircles(true);// 是否有圆点 // lineDataSet.setDrawCircleHole(true);// 设置数据点是空心还是实心,默认空心 lineDataSet.setDrawValues(true);//设置是否显示点的坐标值 // 设置平滑曲线模式 // lineDataSet.setMode(LineDataSet.Mode.STEPPED);//梯形 // lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);//曲线模式 lineDataSet.setMode(LineDataSet.Mode.LINEAR);//折线 // lineDataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);//曲线模式 //设置折线图填充 // lineDataSet.setDrawFilled(true); LineData data = new LineData(lineDataSet); //无数据时显示的文字 lineChart.setNoDataText("暂无数据"); //折线图不显示数值 data.setDrawValues(false); //得到X轴 XAxis xAxis = lineChart.getXAxis(); //设置X轴的位置(默认在上方) xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //设置X轴坐标之间的最小间隔 xAxis.setGranularity(1f); //设置X轴的刻度数量,第二个参数为true,将会画出明确数量(带有小数点),但是可能值导致不均匀,默认(6,false) //xAxis.setLabelCount(list.size() / 6, false); xAxis.setLabelCount(list.size(), false); //设置X轴的值(最小值、最大值、然后会根据设置的刻度数量自动分配刻度显示) xAxis.setAxisMinimum(0f); xAxis.setAxisMaximum((float) list.size()); //不显示网格线 xAxis.setDrawGridLines(false); // 标签倾斜 // xAxis.setLabelRotationAngle(45); //设置X轴值为字符串 可在这里自定义要显示的单位 xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { int IValue = (int) value; CharSequence format = DateFormat.format("MM/dd", System.currentTimeMillis()-(long)(list.size()-IValue)*24*60*60*1000); return format.toString(); } }); Legend mLegend = lineChart.getLegend(); //设置标示,就是那个一组y的value的 // mLegend.setForm(Legend.LegendForm.DEFAULT); //默认圆形样式 // mLegend.setForm(Legend.LegendForm.SQUARE); //方形样式 // mLegend.setForm(Legend.LegendForm.CIRCLE); //圆形样式 mLegend.setForm(Legend.LegendForm.LINE); //横线的样式 mLegend.setFormSize(6f); //字体 // mLegend.setXEntrySpace(6f); //设置在水平轴上 legend-entries 的间隙 mLegend.setYEntrySpace(6f); //设置在垂直轴上 legend-entries 的间隙 mLegend.setFormToTextSpace(6f); //设置 legend-form 和 legend-label 之间的空间 mLegend.setWordWrapEnabled(true); //设置 Legend 是否自动换行? 目前仅支持BelowChartLeft,BelowChartRight mLegend.setTextColor(Color.RED); //设置字体颜色 mLegend.setPosition(Legend.LegendPosition.BELOW_CHART_LEFT); //设置显示下位置在左侧 // mLegend.setPosition(Legend.LegendPosition.BELOW_CHART_RIGHT); //设置显示下位置在右侧 // mLegend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER); //设置显示下位置在中间 // mLegend.setPosition(Legend.LegendPosition.RIGHT_OF_CHART); //设置显示图平行的右侧 // mLegend.setPosition(Legend.LegendPosition.LEFT_OF_CHART); //设置显示图平行的左侧 // mLegend.setPosition(Legend.LegendPosition.RIGHT_OF_CHART_CENTER); //设置显示图平行的右侧据居中 // mLegend.setPosition(Legend.LegendPosition.LEFT_OF_CHART_INSIDE); // // mLegend.setPosition(Legend.LegendPosition.PIECHART_CENTER); //PieChart独有,折线图会显示在中间 // mLegend.setPosition(Legend.LegendPosition.LEFT_OF_CHART_CENTER); //设置显示图平行的左侧据居中 mLegend.setTypeface(Typeface.DEFAULT); //设置图例标签的字体 // mLegend.setForm(Legend.LegendForm.NONE);//不绘制图形 // mLegend.setForm(Legend.LegendForm.EMPTY);;//不绘制图形保留空间 // mLegend.setForm(Legend.LegendForm.LINE); // 线 // mLegend.setFormSize(14f); // 图形大小 // mLegend.setFormLineWidth(9f); // 图形线宽 //隐藏Lengend mLegend.setEnabled(true); // set custom labels and colors // mLegend.setCustom(ColorTemplate.VORDIPLOM_COLORS, // new String[] { "Set1", "Set2", "Set3", "Set4", "Set5" }); LimitLine limitLineL = new LimitLine(8f, "临界点");//临界点 limitLineL.setLineColor(Color.RED); limitLineL.setLineWidth(1.5f); limitLineL.setTextSize(10f); limitLineL.setTextColor(Color.RED); limitLineL.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_TOP);//标签位置 limitLineL.enableDashedLine(5f,8f,0); //设置虚线 lineChart.getAxisLeft().addLimitLine(limitLineL); //设置均值 LimitLine ll2 = new LimitLine(5, "均值"); ll2.setLabel("均值"); ll2.setTextColor(Color.parseColor("#5dbcfe")); ll2.setLineWidth(1f); ll2.setEnabled(true); ll2.setLineColor(Color.parseColor("#5dbcfe")); ll2.enableDashedLine(5f, 10f, 0f);//三个参数,第一个线宽长度,第二个线段之间宽度,第三个一般为0,是个补偿 ll2.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);//标签位置 ll2.setTextSize(10f); lineChart.getAxisLeft().addLimitLine(ll2); //得到Y轴 YAxis yAxis = lineChart.getAxisLeft(); YAxis rightYAxis = lineChart.getAxisRight(); //设置Y轴是否显示 rightYAxis.setEnabled(false); //右侧Y轴不显示 //设置y轴坐标之间的最小间隔 //不显示网格线 yAxis.setDrawGridLines(false); //设置Y轴坐标之间的最小间隔 yAxis.setGranularity(1); //设置y轴的刻度数量 //+2:最大值n就有n+1个刻度,在加上y轴多一个单位长度,为了好看,so+2 yAxis.setLabelCount(Collections.max(list) + 2, false); //设置从Y轴值 yAxis.setAxisMinimum(0f); //+1:y轴多一个单位长度,为了好看 yAxis.setAxisMaximum(Collections.max(list) + 1); //y轴,可在这里设置自定义的单位 yAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { int IValue = (int) value; return String.valueOf(IValue)+"辆"; } }); //图例:得到Lengend // Legend legend = lineChart.getLegend(); //隐藏Lengend // legend.setEnabled(true); //隐藏描述 Description description = new Description(); description.setEnabled(true); lineChart.setDescription(description); lineChart.getDescription().setText("hi"); //折线图点的标记 MyMarkersView mv = new MyMarkersView(this); lineChart.setMarker(mv); //设置数据 lineChart.setData(data); //设置动画效果 lineChart.animateY(2000, Easing.EasingOption.Linear); lineChart.animateX(2000, Easing.EasingOption.Linear); //图标刷新 lineChart.invalidate(); } } |
2.渐变色背景:
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:angle="-90" android:endColor="#FEFFFF" android:startColor="#D9F3FF"></gradient> </shape> |
3.主函数布局:
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 | <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ccc" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.github.mikephil.charting.charts.LineChart android:id="@+id/lineChart" android:layout_width="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:layout_height="220dp" android:layout_centerInParent="true"/> </LinearLayout> </ScrollView> |
4.设置自定义标记提示框
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 | import android.content.Context; import android.text.format.DateFormat; import android.widget.TextView; import com.example.m1571.mympandroidchart.R; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import java.text.DecimalFormat; public class MyMarkersView extends MarkerView { private TextView tvContent; private DecimalFormat format = new DecimalFormat("##0"); public MyMarkersView(Context context) { super(context, R.layout.layout_markerview);//这个布局自己定义 tvContent = (TextView) findViewById(R.id.tvContent); } //显示的内容 @Override public void refreshContent(Entry e, Highlight highlight) { tvContent.setText(format(e.getX())+"\n"+format.format(e.getY())+"辆"); super.refreshContent(e, highlight); } //标记相对于折线图的偏移量 @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2), -getHeight()); } //时间格式化(显示今日往前30天的每一天日期) public String format(float x) { int IValue = (int) x; CharSequence format = DateFormat.format("MM/dd", System.currentTimeMillis()-(long)(list.size()-IValue)*24*60*60*1000); // CharSequence format = DateFormat.format("MM月dd日", // System.currentTimeMillis()-(long) (30-(int)x)*24*60*60*1000); return format.toString(); } } |
5.提示框布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:background="@drawable/bg_shape_c" android:layout_width="match_parent" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="6dp" android:paddingBottom="6dp" android:layout_height="wrap_content"> <TextView android:id="@+id/tvContent" android:text="KING" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> |
6.设置可以左右滑动的折线图效果:
1 2 3 4 5 6 7 8 9 | //xAxis.setLabelCount(list.size() / 6, false);//注意请注释掉这一句代码 lineChart.setVisibleXRange(0, 6); //x轴可显示的坐标范围 lineChart.setDrawGridBackground(false); //表格颜色 lineChart.setGridBackgroundColor(Color.GRAY & 0x70FFFFFF); //表格的颜色,设置一个透明度 lineChart.setTouchEnabled(true); //可点击 lineChart.setDragEnabled(true); //可拖拽 lineChart.setScaleEnabled(false); //可缩放 lineChart.setPinchZoom(false); // lineChart.setBackgroundColor(Color.WHITE); //设置背景颜色 |
7.设置折线中圆点对应的颜色(设置多种颜色值)
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 | //根据数值大小区间来设置圆点对应的颜色 //在方法中判断数值的大小和对应设置的颜色 private static List<Integer> getLineColors(List<Entry> yValues, int normalColor, int exceColor, int exceQcColor) { List<Integer> list = new ArrayList<>(); // float maxSD = (float) (targetValue + sdValue * sdMultiple); // float minSD = (float) (targetValue - sdValue * sdMultiple); float maxSD = 3; float minSD = 0; for (int i = 0; i < yValues.size(); i++) { Entry entry = yValues.get(i); // if (errIndexs.contains(i)) { //限值异常质控不用和sd比较确定显示什么颜色 // list.add(exceQcColor); // continue; // } // if (entry.getVal() >= maxSD || entry.getVal() < minSD) { //此处的entry.getVal()(2.1.6版本)等于entry.getY()(3.0.1版本) if (entry.getY() >= 6) { list.add(exceColor); } else if(entry.getY() == 5){ list.add(normalColor); } else if(entry.getY() < 5){ // list.add(exceQcColor); } } return list; } |
1 2 3 4 | //设置折线圆点多种颜色值 List<Integer> lineColors = getLineColors(entries, Color.RED, Color.YELLOW, Color.BLUE); lineDataSet.setCircleColors(lineColors);// 圆形的颜色 |
8.设置显示折线图圆点的数值,可以自定义单位:
1 2 | //设置圆点显示内容替换原来的%为元 lineDataSet.setValueFormatter(new TestDefaultValueFormatter()); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | //1.在PieChartUtil 中创建内部类 private class TestDefaultValueFormatter implements IValueFormatter { private DecimalFormat mFormat; public TestDefaultValueFormatter(){ mFormat = new DecimalFormat("###");//十进制格式 } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value)+"辆"; } } |
1 | lineDataSet.setDrawValues(true);//设置是否显示点的坐标值 |